Will you help me to figure out why Django raises this error?
SolutionsForLanguagesApp.LanguageLevel: (fields.E336) The model is
used as an in termediate model by
'SolutionsForLanguagesApp.UserProfile.languages', but it does not
have a foreign key to 'UserProfile' or 'Language'.
I'm confused because, as you can see, there is a foreign key to Language in LanguageLevel already:
class LanguageLevel(models.Model):
language = models.ForeignKey(Language)
level = models.ForeignKey(Level)
class Meta:
unique_together = (('level', 'language'),)
Do you know what to do?
EDIT - Added UserProfile:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='userprofile')
date_of_birth = models.DateField(null=True, blank=True)
telephone = models.CharField(max_length=40, null=True, blank=True)
IBAN = models.CharField(max_length=40, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
MARITAL_STATUS_CHOICES = (
('single', 'Single'),
('married', 'Married'),
('separated', 'Separated'),
('divorced', 'Divorced'),
('widowed', 'Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True, blank=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence', u'It was coincidence'),
('relative_or_friends', 'From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True,
blank=True)
# TRANSLATOR ATTRIBUTES
is_translator = models.BooleanField(default=False)
# language_tuples = models.ManyToManyField(LanguageTuple,blank=True)
languages = models.ManyToManyField(Language, through='LanguageLevel')
rating = models.IntegerField(default=0)
number_of_ratings = models.BigIntegerField(default=0)
def __unicode__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
Your LanguageLevel model is missing a ForeignKey to the UserProfile:
class LanguageLevel(models.Model):
language = models.ForeignKey(Language)
level = models.ForeignKey(Level)
# Add Foreign Key to UserProfile
userprofile = models.ForeignKey(UserProfile)
class Meta:
unique_together = (('level', 'language'),)
Also I'm not sure that the unique_together constraint is what you want - it will mean that only one user can have any one combination of language/level. A more likely constraint would be ('userprofile', 'language') so that a language can only be mapped to a user once.
Related
i'm trying to post a transaction via django rest framework, however it shows error in django log as below:
IntegrityError at /api/item_trans/
NOT NULL constraint failed: chemstore_itemtransaction.bin_code_id
it has no problem if I post the same data from the Django admin web.
therefore I suppose the problem has happened at DRF
any help is welcome, thank you
models.py
class BinLocation(models.Model):
bin_code = models.CharField(max_length=10, unique=True)
desc = models.CharField(max_length=50)
def __str__(self):
return self.bin_code
class Meta:
indexes = [models.Index(fields=['bin_code'])]
class ItemMaster(models.Model):
item_code = models.CharField(max_length=20, unique=True)
desc = models.CharField(max_length=50)
long_desc = models.CharField(max_length=150, blank=True)
helper_qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
def __str__(self):
return self.item_code
class Meta:
verbose_name = "Item"
verbose_name_plural = "Items"
indexes = [models.Index(fields=['item_code'])]
class ItemTransaction(models.Model):
# trace_code YYMMDDXXXX where XXXX is random generated
trace_code = models.CharField(max_length=20, unique=False)
item_code = models.ForeignKey(
ItemMaster, on_delete=models.CASCADE, related_name='+', blank=False, null=False)
datetime = models.DateTimeField(auto_now=False, auto_now_add=False)
qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
action = models.CharField(
max_length=1, choices=ACTION, blank=False, null=False)
bin_code = models.ForeignKey(
BinLocation, related_name='+', on_delete=models.CASCADE, blank=False, null=False)
remarks = models.TextField(blank=True)
def __str__(self):
return f"{self.trace_code} {self.datetime} {self.item_code} {dict(ACTION)[self.action]} {self.qty} {self.unit} {self.bin_code}"
serializers.py
class ItemMasterSerializer(serializers.ModelSerializer):
class Meta:
model = ItemMaster
fields = '__all__'
class ItemTransactionSerializer(serializers.ModelSerializer):
item_code = serializers.SlugRelatedField(
slug_field='item_code',
read_only=True
)
bin_code = serializers.SlugRelatedField(
slug_field='bin_code',
read_only=True,
allow_null=False
)
class Meta:
model = ItemTransaction
fields = '__all__'
You might need to use 2 fields, one for reading data and the other for creating and updating your data with its source to the main. In your case you could try this:
class ItemTransactionSerializer(serializers.ModelSerializer):
item_code_id = ItemMasterSerializer(read_only=True)
item_code = serializers.PrimaryKeyRelatedField(
queryset=ItemMaster.objects.all(),
write_only=True,
source='item_code_id'
)
bin_code_id = BinLocationSerializer(read_only=True
bin_code = serializers.PrimaryKeyRelatedField(
queryset= BinLocation.objects.all(),
write_only=True,
source='bin_code_id'
)
Since you have null=False in both of your ForeignKeys, DRF expects the corresponding ID. You seem to be getting the error NOT NULL constraint because you are not passing the ID in DRF. So you need to fix that for both bin_code_id and the item_code_id.
How to solve this error? cause
whenever I search the student user I received an error,
error
admin.py
#admin.register(StudentsEnrollmentRecord)
class StudentsEnrollmentRecordAdmin(admin.ModelAdmin):
#inlines = [InLineSubject]
list_display = ('lrn', 'Student_Users', 'Education_Levels', 'Courses', 'Section', 'Payment_Type', 'Discount_Type' ,'School_Year')
#list_select_related = ('Student_Users')
ordering = ('Education_Levels','Student_Users__lrn')
list_filter = ('Student_Users','Education_Levels','Section','Payment_Type')
search_fields = ('Student_Users',)
def lrn(self, obj):
return obj.Student_Users.lrn
my models.py
class StudentsEnrollmentRecord(models.Model):
Student_Users = models.ForeignKey(StudentProfile, related_name='students', on_delete=models.CASCADE,null=True)
School_Year = models.ForeignKey(SchoolYear, related_name='+', on_delete=models.CASCADE, null=True, blank=True)
Courses = models.ForeignKey(Course, related_name='+', on_delete=models.CASCADE, null=True, blank=True)
Section = models.ForeignKey(Section, related_name='+', on_delete=models.CASCADE, null=True,blank=True)
Payment_Type = models.ForeignKey(PaymentType, related_name='+', on_delete=models.CASCADE, null=True)
Discount_Type = models.ForeignKey(Discount, related_name='+', on_delete=models.CASCADE, null=True,blank=True)
Education_Levels = models.ForeignKey(EducationLevel, related_name='+', on_delete=models.CASCADE,blank=True,null=True)
UPDATE models
class StudentProfile(models.Model):
lrn = models.CharField(max_length=500,null=True)
Firstname = models.CharField(max_length=500,null=True,blank=True)
Middle_Initial = models.CharField(max_length=500,null=True,blank=True)
Lastname = models.CharField(max_length=500,null=True,blank=True)
Education_Levels= models.ForeignKey(EducationLevel, on_delete=models.CASCADE,blank=True,null=True)
You need to provide a specific field from StudentProfile - currently your search field is
search_fields = ('Student_Users',)
which means only the model itself. You didn't post a schema of your StudentProfile, but for example if it contains a Lastname field, you should use it like this:
search_fields = ('Student_Users__Lastname',)
To include multiple fields you can do
search_fields = ('Student_Users__Lastname', 'Student_Users__Firstname',)
You could also do
search_fields = ('=Student_Users__Lastname',)
to match the last name "exactly", previous example checks whether the field contains the query string
I have a created Django-CMS Plugin with a ManytoManyField to another model. When creating the Plugin on the Front-End, i want the user to be able to filter the ManytoManyField list (which might be too long).
By the way this future is already on Django admin:
class ModelAdmin(admin.ModelAdmin):
list_filter = ('field_name', )
form = PartnerLogoTableForm
Is it possible to have something similar like that on my
cms_plugins.py:
class PartnerLogoTablePlugin(CMSPluginBase):
model = LogoTablePlugin
form = LogoTablePluginForm
name = _('LogoTable Plugin')
render_template = False
search_fields = ('description',)
def render(self, context, instance, placeholder):
self.render_template = 'aldryn_logo_tables/plugins/%s/logotable.html' % instance.style
context.update({
'object': instance,
'placeholder': placeholder,
})
return context
plugin_pool.register_plugin(PartnerLogoTablePlugin)
models.py:
class PartnerLogoTable(models.Model):
name = models.CharField(_('Partner name'), max_length=255)
image = FilerImageField(verbose_name=_('Image'), null=True, blank=True, on_delete=models.SET_NULL)
partner_url = models.TextField(_('Partner url'), null=True, blank=True, validators=[URLValidator()])
is_active = models.BooleanField(_('Is active'), blank=True, default=True)
created_at = models.DateTimeField(_('Created at'), auto_now_add=True)
updated_at = models.DateTimeField(_('Updated at'), auto_now=True)
order = models.IntegerField(_('Order'), null=True, blank=True)
class Meta:
verbose_name = _('Partner Logo')
verbose_name_plural = _('Partner Logos')
ordering = ['order']
def __str__(self):
return self.name
class LogoTablePlugin(CMSPlugin):
DEFAULT = 'default'
LOGOTABLE_CHOICES = [
(DEFAULT, _('Default')),
]
description = models.CharField(_('Description'), max_length=255, null=True, blank=True)
partner = models.ManyToManyField(PartnerLogoTable, verbose_name=_('Partner'))
logo_per_row = models.IntegerField(_('Logo per line'), default=1, null=True, blank=True,
validators=[MaxValueValidator(4), MinValueValidator(1)],
help_text=_('Number of logos to be displayed per row'))
style = models.CharField(_('Style'), choices=LOGOTABLE_CHOICES + get_additional_styles(), default=DEFAULT,
max_length=50, blank=True, null=True, )
class Meta:
verbose_name = _('Partner Logo Plugin')
verbose_name_plural = _('Partner Logo Plugins')
def __unicode__(self):
return u'%s' % self.description
forms.py
class LogoTablePluginForm(forms.ModelForm):
model = LogoTablePlugin
def clean_style(self):
.....
return style
class PartnerLogoTableForm(forms.ModelForm):
model = PartnerLogoTable
def clean(self):
....
return self.cleaned_data
This is how the plugin looks now
ModelSelect2Multiple from django-autocomplete-light seems perfect for your use case.
here is my model, serializer and output but when i want to create a new page it ask me to add a whole new user as its just a foreign-key it need to be a number like 1 (user id) and same in the case of categories how can i solve it.... help me please
serializers.py
class TeamMembersSerializer(serializers.ModelSerializer):
class Meta:
model = TeamMembers
fields = [
'user',
'page',
]
depth = 1
class SocialAccountsSerializer(serializers.ModelSerializer):
social = SocialCatSerializer()
class Meta:
model = SocialAccounts
fields = [
'page',
'social',
'link'
]
depth = 1
class PageImageSerializer(serializers.ModelSerializer):
class Meta:
model = PageImages
fields = [
'page',
'image',
]
depth = 1
class PageSerializer(serializers.ModelSerializer):
owner = UserSerializer()
catagory = BusinessCatSerializers()
business_type = BusinessTypeSerializer()
TeamMembers = TeamMembersSerializer(read_only=True)
social_accounts = SocialAccountsSerializer(read_only=True)
images = PageImageSerializer(read_only=True)
class Meta:
model =Page
fields = [
'id',
'owner',
'catagory',
'name',
'username',
'images',
'start_date',
'business_type',
'contect_number',
'email_address',
'website',
'TeamMembers',
'social_accounts',
'about',
'impression',
'Awards',
'Product',
'privacy_policy',
'is_active',
]
Models.py
class Page(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
catagory = models.ForeignKey(BusinessCatagories, on_delete=models.CASCADE, null=True, blank=True, default=None)
name = models.CharField(max_length=254, unique=True ,default=None, blank=True)
username = models.CharField(max_length=254, unique=True, blank=True)
start_date = models.DateTimeField(auto_now_add=True)
business_type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, null=True, blank=True, default=None)
contect_number = models.CharField(max_length=254, default=None, blank=True)
email_address = models.EmailField(default=None, blank=True)
website = models.URLField(default=None, blank=True)
about = models.TextField(default=None, blank=True)
impression = models.TextField(default=None, blank=True)
Awards = models.CharField(max_length=254, default=None, blank=True)
Product = models.CharField(max_length=254, default=None, blank=True)
privacy_policy = models.URLField(default=None, blank=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class TeamMembers(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None, blank=True)
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
def __str__(self):
return self.user.name
class SocialAccounts(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
social = models.ForeignKey(SocialCats, on_delete=models.CASCADE, default=None, blank=True)
link = models.URLField(default=None, blank=True)
def __str__(self):
return self.link
class PageImages(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
image = models.ImageField(default=None, blank=True, upload_to=settings.MEDIA_ROOT)
def __str__(self):
return self.page.name
output is this but i need images field TeamMember field in it but its not appearing plus it want me to add a new user instead of asking for Foreignkey "id"
What you want is to use Primary key related field. It helps you to represent the target of the relationship using its primary key.
It should look somewhat like this.
Note: Mind the typo for any name
class PageSerializer(serializers.ModelSerializer):
owner = serializers.PrimaryKeyRelatedField(queryset = User.objects.all())
catagory = serializers.PrimaryKeyRelatedField(queryset = BuisnessCat.objects.all())
business_type = BusinessTypeSerializer()
TeamMembers = TeamMembersSerializer(read_only=True)
social_accounts = SocialAccountsSerializer(read_only=True)
images = PageImageSerializer(read_only=True)
You can read more about PrimaryKeyRelatedField here.
Now whenever creating any Page, all you need to supply are primary key for owner and category.
You are looking for Writable Nested Serializer.
In short you have to override create() method of PageSerializer
class PageSerializer(serializers.ModelSerializer):
....
....
your code
def create(self, validated_data):
# pop data of every related fields like "owner", "cateagory" etc from validated_data
owner = validated_data.pop("owner")
owner = User.objects.create(**owner)
category = validated_data.pop("category")
# create or retrieve category instance ,as above
...
...
...
# finally
return Page.objects.create(**validated_data,owner=owner,category=category, and other related instances)
I changed models.py adding through-model for one of my old models. I't UserProfileLanguage which is a relation between UserProfile, Language and Level. Each UserProfile can have multiple Languages on different Levels (skills).
Now I looked at the Django-admin to see whether I can add manualy Languages with their Levels to the UserProfile but I can't see it there.
Do you know where could be the problem?
I've commented the attribute languages in UserProfile model so you can see it.
Here is my models.py:
from __future__ import unicode_literals
# from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import User
from django.db import models
class AdminContact(models.Model):
email = models.EmailField()
telephone = models.CharField(max_length=40)
def __unicode__(self):
return self.email
class Language(models.Model):
shortcut = models.CharField(max_length=40)
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class Level(models.Model):
LEVEL_CHOICES = (
('standard','Standard level'),
('professional','Professional level'),
('native','Native speaker level'),
)
name = models.CharField(max_length=40,choices=LEVEL_CHOICES, blank=False, null=False)
price_multiplier = models.FloatField()
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='userprofile')
date_of_birth = models.DateField(null=True,blank=True)
telephone = models.CharField(max_length=40,null=True,blank=True)
IBAN = models.CharField(max_length=40,null=True,blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
MARITAL_STATUS_CHOICES = (
('single', 'Single'),
('married', 'Married'),
('separated', 'Separated'),
('divorced', 'Divorced'),
('widowed', 'Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True, blank=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence', u'It was coincidence'),
('relative_or_friends', 'From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True,
blank=True)
# TRANSLATOR ATTRIBUTES
is_translator = models.BooleanField(default=False)
language_tuples = models.ManyToManyField(LanguageTuple,blank=True)
# I CANT SEE THIS ATTRIBUTE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
languages = models.ManyToManyField(Language, through='UserProfileLanguage')
rating = models.IntegerField(default=0)
number_of_ratings = models.BigIntegerField(default=0)
def __unicode__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
class UserProfileLanguage(models.Model):
userprofile = models.ForeignKey(UserProfile)
language = models.ForeignKey(Language)
level = models.ForeignKey(Level)
class Meta:
unique_together = (('userprofile', 'language'),)
class Job(models.Model):
customer = models.ForeignKey(User, related_name='orders')
translator = models.ForeignKey(User, related_name='jobs',null=True)
price = models.FloatField(null=True,blank=True)
# ZADAVA CUSTOMER
description = models.TextField()
file = models.FileField(null=True,blank=True)
language_tuple = models.ForeignKey(LanguageTuple,related_name='jobs')
specialist = models.BooleanField(blank=True)
# AUTOMATICKY GENEROVANE
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=False)
is_done = models.BooleanField(default=False)
#property
def has_translator(self):
return self.translator_id is not None
def __str__(self):
return '{}: {}'.format(self.customer,self.language_tuple)