I have created a field in Settings->Configuration->Accounting.
The field is default customer account. Many2one field (account_id)
I have given widget="selection" in XML.
When after clicking on Apply Button,The default customer account is present.
After any one transactions or after logout and if again loggedin , then the field I selected is empty.
It will be resolved by get_param and set_param
code
from openerp.osv import fields, osv
from openerp.tools.safe_eval import safe_eval
class stock_config_settings(osv.osv_memory):
_inherit = 'stock.config.settings'
_columns = {
'default_stock_id' : fields.many2one('stock.location','Stock Location', required=True),
}
def get_default_stock(self, cr, uid, fields, context=None):
icp = self.pool.get('ir.config_parameter')
return {
'default_stock_id': safe_eval(icp.get_param(cr, uid, 'default_stock.default_stock_id', 'False')),
}
def set_default_stock(self, cr, uid, ids, context=None):
config = self.browse(cr, uid, ids[0], context=context)
icp = self.pool.get('ir.config_parameter')
icp.set_param(cr, uid, 'default_stock.default_stock_id', (config.default_stock_id.id))
By the above code, the value will be set properly.
Related
I am working on creating a widget so clients can easily modify model's Json field in django admin.
Env Info:
django-version: 3.1.14
Before drive into the widget, this is a simplify version of my model:
class Property(PolymorphicModel):
"""Basic information about property"""
...
address = models.JSONField(blank=True, null=True, default=dict,)
...
And this how I am declaring the form:
class PropertyForm(forms.ModelForm):
class Meta:
model = Property
fields = [
"address",
]
widgets = {
'address': JSONEditorWidget(),
}
I've already manage to convert json file into django admin inputs by using the following code:
class JSONEditorWidget(forms.widgets.Input):
def as_field(self, name, key, value):
""" Render key, value as field """
new_name = name + '__' + key
self.attrs = self.build_attrs({new_name:key})
self.attrs['value'] = utils.encoding.force_text(value)
return u'%s: <input%s />' % (new_name, forms.utils.flatatt(self.attrs))
def to_fields(self, name, json_obj):
"""Get list of rendered fields for json object"""
inputs = []
for key, value in json_obj.items():
inputs.append(self.as_field(name, key, value))
return inputs
def value_from_datadict(self, data, files, name):
"""I've been trying to get new values in this function but nothing successful"""
return json.dumps(prev_dict)
def render(self, name, value, attrs=None, renderer = None):
# TODO: handle empty value (render text field?)
if value is None or value == '':
value = '{}'
json_obj = json.loads(value)
inputs = self.to_fields(name, json_obj)
# render json as well
inputs.append(value)
return utils.safestring.mark_safe(u"<br />".join(inputs))
with this I could go from this:
To this:
My problem now is to catch the new values when user clicks on save/save and continue, so I can convert them into json file to save new records on postgres.
Ive tried with the function value_fromdatadict() but couldn't manage a way to get new values in the input box...
If anyone can helps me I will be so glad, I've been dealing with this a while and this is driving me crazy
I created an update mutation as follows, with django==3.1.4 and graphene==2.1.8 :
# models.py
class CustomUser(AbstractUser):
# email = models.EmailField()
firebase_id = models.CharField(max_length=50, null=True)
nickname = models.CharField(max_length=50, null=True)
name = models.CharField(max_length=20, null=True)
gender = models.IntegerField(choices=Gender, default=3)
phone = models.CharField(max_length=20, null=True)
birthday = models.DateField(default=datetime(2020,1,1))
address = models.CharField(max_length=200, null=True)
profile_image = models.ImageField(default='default-avatar.png', upload_to='users/',
null=True, blank=True)
class UpdateMember(graphene.Mutation):
class Arguments:
firebase_id = graphene.String(required=True)
nickname = graphene.String()
name = graphene.String()
gender = graphene.Int()
phone = graphene.String()
birthday = graphene.Date()
address = graphene.String()
profile_image = graphene.String()
class Meta:
exclude = ["password"]
member = graphene.Field(MemberType)
success = graphene.Boolean()
# #login_required
#staticmethod
def mutate(root, info, firebase_id, **kwargs):
success = False
member_instance = CustomUser.objects.get(firebase_id=firebase_id)
if member_instance:
print(member_instance)
success = True
for k, v in kwargs.items():
member_instance.k = v
member_instance.save()
return UpdateMember(member=member_instance, success=True)
else:
return UpdateMember(member=None, success=False)
Running GQL below:
mutation {
updateMember(
firebaseId:"777",
name:"JJJJ")
{
success
}
}
Response:
{
"data": {
"updateMember": {
"success": true
}
}
}
But I checked the database, it seems no change in it, I think .save() should have done the work persisting changes to database......
Creating Member works fine. Using PostgresQL
Could anyone figure out why?
There is several issues in your code:
You can not assign your model fields using string like that. See this thread
for k, v in kwargs.items():
member_instance.k = v
member_instance.save()
Currently your member_instance.k has nothing to do with variable k inside for loop.
firebase_id field should be unique.
Currently you call CustomUser.objects.get(firebase_id=firebase_id) which is risky because firebase_id is not unique field. This may lead Multiple objects error if you have more than one CustomUsers saved with same id. To fix it, just define:
class CustomUser(AbstractUser):
# email = models.EmailField()
firebase_id = models.CharField(max_length=50, unique=True)
...
To check if your member_instance has really updated. You can for example print out the values before saving it and run some test cases before final implementation. For example:
if member_instance:
print(member_instance)
success = True
for k, v in kwargs.items():
member_instance.k = v
print(member_instance.k)
print(k)
print(getattr(member_instance, k))
member_instance.save()
In my app, i have a chained dropdown in which i am getting the second dropdown via jquery ajax, which works well.So i am trying to edit this saved data and load it back to an edit form, but the dropdown is showing empty. This is what i have done so far
Here is my model.py
class SchoolFees(models.Model):
fid = models.ForeignKey(FacultyData, on_delete= models.SET_NULL, null=True)
did = models.ForeignKey(DepartmentData, on_delete= models.SET_NULL, null=True)
sid = models.ForeignKey(SessionData, on_delete= models.SET_NULL, null=True)
amount = models.CharField(max_length=30)
def __str__(self):
return self.amount
forms.py
class FeesCreationForm(forms.ModelForm):
fid = forms.ModelChoiceField(queryset=FacultyData.objects.all(), empty_label="--Select Faculty--",
widget=forms.Select(attrs={'class': 'form-control'}))
did = forms.ModelChoiceField(queryset=DepartmentData.objects.all(), empty_label="--Select Faculty First--",
widget=forms.Select(attrs={'class': 'form-control'}))
sid = forms.ModelChoiceField(queryset=SessionData.objects.all(), empty_label="--Select Session--",
widget=forms.Select(attrs={'class': 'form-control'}))
class Meta:
model = models.SchoolFees
fields = ['sid', 'fid', 'did', 'amount']
widgets = {
'amount': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Amount'})
}
def __init__(self, *args, **kwargs):
super(FeesCreationForm, self).__init__(*args, **kwargs)
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fd = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(fid_id=fd).order_by('id')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and use empty queryset
Here is my view.py
def edit_fee(request, pk):
app = settings.CONFIG
post = get_object_or_404(SchoolFees, pk=pk)
if request.method == 'POST':
form = FeesCreationForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.add_message(request, messages.WARNING, "Fees record updated successfully")
return redirect('bursary:create_fee')
else:
# bring edit form out
form = FeesCreationForm(instance=post)
table = FeesTable(SchoolFees.objects.all())
RequestConfig(request, paginate={'per_page': 10}).configure(table)
context = {"form": form, "fees": table, 'app': app}
return render(request, 'editfee.html', context)
I expect that the saved value is pass to the dropdown with other form fields which are already showing
After going through this post, i was able to solve it when reading the comments. All i needed was to add a backward relationship to my init function.
class FeesCreationForm(forms.ModelForm):
fid = forms.ModelChoiceField(queryset=FacultyData.objects.all(), empty_label="--Select Faculty--",
widget=forms.Select(attrs={'class': 'form-control'}))
did = forms.ModelChoiceField(queryset=DepartmentData.objects.all(), empty_label="--Select Faculty First--",
widget=forms.Select(attrs={'class': 'form-control'}))
sid = forms.ModelChoiceField(queryset=SessionData.objects.all(), empty_label="--Select Session--",
widget=forms.Select(attrs={'class': 'form-control'}))
class Meta:
model = models.SchoolFees
fields = ['sid', 'fid', 'did', 'amount']
widgets = {
'amount': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Amount'})
}
def __init__(self, *args, **kwargs):
super(FeesCreationForm, self).__init__(*args, **kwargs)
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fd = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(fid_id=fd).order_by('id')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and use empty queryset
elif self.instance.pk:
self.fields['did'].queryset = self.instance.fid.departmentdata_set.order_by('id')
#backward relation - for this faculty selected, check its deparm
#every department has its faculty
# #in other word, which dept has their foreign key pointing to the current instance of faculty
I'm trying to override create and copy methods so that whenever i execute any of this methods my sequence number auto-increment, here is the create method:
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
data_obj = self.pool.get('ir.model.data')
sequence_ids = data_obj.search(cr, uid, [('name','=','seq_tour_booking')], context=context)
sequence_id = data_obj.browse(cr, uid, sequence_ids[0], context=context).res_id
if vals.get('name','/') =='/':
code = self.pool.get('ir.sequence').get_id(cr, uid, sequence_id, 'id', context) or '/'
vals['name'] = code
return super(tour_booking, self).create(cr, uid, vals, context=context)
any ideas for the copy method?
thank you.
MAybe I'm wrong, but you shouldn't need to override also copy because it calls create: thus overriding it should be enough.
I tried this and it worked :
def copy(self, cr, uid, id, default=None, context=None):
if default == None:
default = {}
default['name'] = self.pool.get('ir.sequence').get(cr, uid,'your.object.name')
return super(your_class_name, self).copy(cr, uid, id, default, context=context)
I am using python-social-auth and django-rest-framework to allow users signup with their social accounts in my app.
my case is similar to this post
Users are not created after login with facebook (probably an homonymy case)
I use django-rest-framework's TokenAuthentication to authenticate users
When using my custom user model, when an authtoken is available in the header (user is logged in) the social user account created is linked to the user whose Token is attached to the request as expected, but when there is no token available, it fails to create a new account.
But when using the default django user model, everything works as expected. I suspect that I am not configuring my custom user model properly.
Below is my settings file can you please look and see if you can find out what I am doing wrong.
Thanks in advance.
My settings file
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
),
'PAGINATE_BY': 10
}
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.request',
'social.apps.django_app.context_processors.backends',
)
SOCIAL_AUTH_FACEBOOK_KEY = os.environ.get('FB_APP_ID')
SOCIAL_AUTH_FACEBOOK_SECRET = os.environ.get('FB_APP_SECRET')
SOCIAL_AUTH_FACEBOOK_EXTENDED_PERMISSIONS = ['email']
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_USER_MODEL = 'users.FLUser'
SOCIAL_AUTH_TWITTER_KEY = os.environ.get('TWITTER_APP_ID')
SOCIAL_AUTH_TWITTER_SECRET = os.environ.get('TWITTER_APP_SECRET')
AUTHENTICATION_BACKENDS = (
'social.backends.twitter.TwitterOAuth',
'social.backends.facebook.FacebookOAuth2',
'social.backends.facebook.Facebook2OAuth2',
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
# 'apps.users.pipeline.user_details',
)
Custom Manager
class FLUserManager(BaseUserManager):
def _create_user(self, username, email, password,
is_staff, is_superuser, **extra_fields):
"""
Creates and saves a User with the given username, email and password.
"""
now = timezone.now()
if not email:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, False, False,
**extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
return self._create_user(username, email, password, True, True,
**extra_fields)
Custom User Model
class FLUser(AbstractBaseUser, PermissionsMixin):
GENDER = (
('M', 'Male'),
('F', 'Female'),
)
email = models.EmailField(
verbose_name=_('email address'),
max_length=255,
unique=True,
)
username = models.CharField(
verbose_name=_('username'),
max_length=30,
unique=False,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'#/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'),
_('Enter a valid username.'), 'invalid')
]
)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
birthday = models.DateTimeField(
blank=True,
default=None,
null=True
)
gender = models.CharField(
max_length=1,
choices=GENDER,
default=None,
null=True
)
avatar = models.ImageField(
upload_to='media/avatars',
blank=True,
default=None,
null=True
)
sm_avatar = models.URLField(
blank=True,
default=None,
null=True,
verbose_name=_('Social Media Avatar')
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
)
is_admin = models.BooleanField(default=False)
objects = FLUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'username',]
def is_authenticated(self):
return True
def get_full_name(self):
return '''{} {}'''.format(self.first_name, self.last_name)
def get_short_name(self):
return self.first_name
#property
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
# On Python 3: def __str__(self):
def __unicode__(self):
return self.email
def email_user(self, subject, message, from_email=None):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email])
class Meta:
ordering = ('id', 'first_name',)
verbose_name = _('user')
verbose_name_plural = _('users')
#receiver(post_save, sender=FLUser)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
The View
#api_view(['POST'])
#permission_classes((AllowAny,))
#strategy()
def register_by_access_token(request, backend):
backend = request.strategy.backend
if backend.name == 'twitter':
token = {
'oauth_token': request.DATA.get('access_token'),
'oauth_token_secret': os.environ.get('TWITTER_APP_OAUTH_SECRET'),
}
elif backend.name == 'facebook':
token = request.POST.get('access_token')
else:
raise Response('Wrong backend type', status=HTTP_400_BAD_REQUEST)
user = backend.do_auth(
access_token=token,
user=request.user.is_authenticated() and request.user or None
)
if user and user.is_active:
login(request, user)
user = UserAuthSerializer(user)
return Response(user.data, status=HTTP_200_OK)
else:
return Response({'detail': 'Unable to authenticate user'}, status=HTTP_400_BAD_REQUEST)
not sure if this matters at all, but i think your inheritance is a little wrong for your custom user model (mixins come before):
class FLUser(PermissionsMixin, AbstractBaseUser):
....