I have a model of product and another model called Course that inherits the product but has a video field and an author Which is a ForeignKey with A teacher model which inherits from the user model which inherits from AbstractUser
Related Models:
class User(AbstractUser):
username = models.SlugField(default="", null=False, db_index=True, blank=True) # forced by django admin problems :(
password = models.CharField(max_length=255, null=True)
email = models.EmailField(max_length=255, unique=True)
group = models.ManyToManyField(Group)
is_teacher = models.BooleanField(default=False, null=False)
is_seller = models.BooleanField(default=False, null=False)
phoneNum = PhoneNumberField(null=False, unique=True, default='')
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "first_name", "last_name", "password"]
def save(self, *args, **kwargs):
self.username = slugify(self.first_name + self.last_name)
super().save(*args, **kwargs)
class Product(models.Model):
name = models.CharField(max_length=100, null=False, blank=True)
shoppers = models.ManyToManyField(User, related_name='shopper')
tumb = models.ImageField(upload_to=course_tumb_directory_path, null=False)
lastUpdate = models.DateTimeField(auto_now=True)
price = models.DecimalField(null=False, default=1000000, max_digits=7, decimal_places=0)
class Teacher(User):
TOPICS = [
("BP", "Basic Programming"),
("AP", "Advanced Programming"),
("CS", "Computer Science"),
("MS", "Mathematics"),
("CH", "Chemistry"),
("BL", "BioLogy"),
("PH", "physics"),
("EL", "Electronics"),
("RG", "Religious"),
("Or", "Other"),
]
topic = models.CharField(max_length=2, choices=TOPICS, default=TOPICS[-1][0])
class Course(Product):
video = models.FileField(upload_to=course_directory_path, null=True,
validators=[
FileExtensionValidator(allowed_extensions=['MOV', 'avi', 'mp4', 'webm', 'mkv'])])
author = models.ForeignKey(Teacher, on_delete=models.CASCADE, null=True)
when I'm trying to make migrations it says this:
It is impossible to add a non-nullable field 'product_ptr' to course without specifying a default. This is because the database needs something to populate existing rows.
I'm using PostgreSQL for my db, It didn't let me flush it so I Dropped it and ReCreated a new one
But I Still can't makemigrations
I tried these answers:
You are trying to add a non-nullable field 'new_field' to userprofile without a default
Django: You are trying to add a non-nullable field 'slug' to post without a default; we can't do that
It is impossible to add a non-nullable field 'id' to video without specifying a default
You are trying to add a non-nullable field 'id' to contact_info without a default
Error : "You are trying to add a non-nullable field"
I faced these kinds of errors before but one thing I couldn't figure out is that it isn't related to a field so I can't fix it
Python: 3.10.6
Django: 4.1
PostgreSQL: psql 14.6
OS: Ubuntu 22.04 (Not a VM)
I figured out that so many repetitive inheritances made this error not sure why but this solves it:
class BaseProduct(models.Model):
class Meta:
abstract = True
name = models.CharField(max_length=100, null=False, blank=True)
shoppers = models.ManyToManyField(User)
tumb = models.ImageField(upload_to=course_tumb_directory_path, null=False, blank=True)
lastUpdate = models.DateTimeField(auto_now=True)
price = models.DecimalField(null=False, default=1000000, max_digits=7, decimal_places=0)
class Product(BaseProduct):
count = models.DecimalField(null=False, default=1, max_digits=7, decimal_places=0)
class Course(BaseProduct):
video = models.FileField(upload_to=course_directory_path, null=True,
validators=[
FileExtensionValidator(allowed_extensions=['MOV', 'avi', 'mp4', 'webm', 'mkv'])])
author = models.ForeignKey(Teacher, on_delete=models.CASCADE, null=True, related_name='courses')
Inheriting from an abstract model instead of repetitive Inheritance
Related
I have a parent model which is Profile and two other models which is Courses and Course_student.
class Profile(models.Model):
...
first_name = models.CharField(verbose_name=_('First Name'), max_length=255, null=True, blank=True, )
middle_name = models.CharField(verbose_name=_('Middle Name'), max_length=255, null=True, blank=True)
last_name = models.CharField(verbose_name=_('Last Name'), max_length=255, null=True, blank=True)
...
class Courses(models.Model):
YESNO = (
('Yes', 'Yes'),
('No', 'No'),
)
profile = models.ManyToManyField('Profile', related_name='course_profile', verbose_name=_('Profile'))
course_taken = models.CharField(verbose_name=_('Course'), max_length=255)
name_of_school = models.CharField(verbose_name=_('Name of School'), max_length=255)
school_location = models.CharField(verbose_name=_('School Location'), max_length=255)
period_of_attendance_from = models.DateField(verbose_name=_('Period of Attendance (From)'), max_length=255)
period_of_attendance_to = models.DateField(verbose_name=_('Period of Attendance (To)'), max_length=255)
nr_students = models.IntegerField(verbose_name=_('Total Number of Students'), null=True, blank=True)
created_on = models.DateTimeField(auto_now_add=True)
modified_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = _('Course')
verbose_name_plural = _('Course')
def __str__(self):
return '%s' % (self.course_taken)
class Course_student(models.Model):
YESNO = (
('Yes', 'Yes'),
('No', 'No'),
)
course = models.ForeignKey('Courses', related_name='course_student_details', on_delete=models.DO_NOTHING, verbose_name=_('Course'), blank=True, null=True)
profile = models.ForeignKey('Profile', related_name='course_student_profile', on_delete=models.DO_NOTHING, verbose_name=_('Profile'), blank=True, null=True)
standing = models.IntegerField(verbose_name=_('Standing'), null=True, blank=True)
grade = models.CharField(verbose_name=_('Grade'), max_length=255, null=True, blank=True)
completed = models.CharField(verbose_name=_('Completed'), choices=YESNO, max_length=255)
class Meta:
verbose_name = _('Student Details')
verbose_name_plural = _('Student Details')
def __str__(self):
return '%s' % (self.course)
admin.py
class CourseUploaderInline(admin.StackedInline):
model = CourseUploader
extra = 1
class CourseStudentInline(admin.StackedInline):
model = Course_student
extra = 1
#admin.register(Courses)
class CoursesAdmin(admin.ModelAdmin):
inlines = [Course_studentInline, CorseUploaderInline,]
Course_student has Foreignkey to Courses and Profile
As you can see, Course_student has fields for profile, standing, grade and completed, this will hold the details of the student for a particular course and particular profile/student.
while Courses has M2M to Profile so that I can tag the student what courses she/he have.
Profile will hold the basic information of the student
What I am trying to do is, combine the Courses and Course_student by filtering using the Profile such as:
view.py
def profile(request, pk):
profile = Profile.objects.filter(profile=pk)
course = Course.objects.filter(profile=pk) # I tried here the select_related()
P.S. I am new to Django and Python, I hope you'll be easy on me :) TIA
Suggestion is also welcome on what I'm trying to achieve.
After sometime troubleshooting my queryset using the select_related(), I found out that the problem is on my template syntax that displays' the combine course and course_student list
I was using the syntax {{ course.name_of_school }} instead of {{ course.course.name_of_school }} in my template.
Using the select_related() is the correct way to follow the reverse relationship. I just missed the syntax on the template.
course = Course_student.objects.select_related('course').filter(profile=pk)
Finally, I can sleep now.
I have Profile Model that have instance model user.. I am trying to create group using form. that group model have Profile model as instance, so how do I select authenticated user automatic to create group, I getting confused...
This is my Group Model
class Groups(models.Model):
profile = models.ForeignKey(Profile, related_name='my_groups', on_delete=models.CASCADE)
groups_name = models.CharField(max_length=150)
slug = models.SlugField(max_length=150, unique=True)
cover_pic = models.ImageField(upload_to='images/groups/', null=True, blank=True)
type_group = models.CharField(max_length=150)
created_date = models.DateTimeField(auto_now_add=True)
about_group = models.TextField(max_length=600)
members = models.ManyToManyField(Profile,through="GroupMember")
def __str__(self):
return self.groups_name
This is my profile Model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
slug = models.SlugField(max_length=100, unique=True)
profile_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
cover_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
user_bio = models.TextField(null=True,blank=True, max_length=255)
designation = models.CharField(blank=True,null=True, max_length=255)
education = models.CharField(blank=True, null=True, max_length=255)
marital_status = models.CharField(blank=True, null=True, max_length=60)
hobbies = models.CharField(blank=True, null=True, max_length=500)
location = models.CharField(blank=True, null=True, max_length=500)
mobile = models.IntegerField(blank=True, null=True)
def __str__(self):
return str(self.user)
This is form for create group
class GroupCreateForm(forms.ModelForm):
class Meta:
model = Groups
fields = ('cover_pic', 'profile', 'groups_name', 'type_group', 'about_group')
profile = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control input-group-text',
'value':'',
'id':'somesh',
'type': 'hidden',
}))
This is create group html file
this is html page
this is error..
You have set a CharField for profile in your form. When you send data to this form, it tries to make a Group record with a FK to a CharField for example "1" and this gives you error because you should pass Profile object to Group.
Depends on what exactly you want, there are some options.
You can use ModelChoiceField. Read about it in https://docs.djangoproject.com/en/3.2/ref/forms/fields/#django.forms.ModelChoiceField
Or you can use Inline FormSet and read about it in https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets
And an example for Inline FormSet in Creating a model and related models with Inline formsets
at the moment I try to get recipes from my API. I have a Database with two tables one is with recipes and their ids but without the ingredients, the other table contains the ingredients and also the recipe id. Now I cant find a way that the API "combines" those. Maybe its because I added in my ingredient model to the recipe id the related name, but I had to do this because otherwise, this error occurred:
ERRORS:
recipes.Ingredients.recipeid: (fields.E303) Reverse query name for 'Ingredients.recipeid' clashes with field name 'Recipe.ingredients'.
HINT: Rename field 'Recipe.ingredients', or add/change a related_name argument to the definition for field 'Ingredients.recipeid'.
Models
from django.db import models
class Ingredients(models.Model):
ingredientid = models.AutoField(db_column='IngredientID', primary_key=True, blank=True)
recipeid = models.ForeignKey('Recipe', models.DO_NOTHING, db_column='recipeid', blank=True, null=True, related_name='+')
amount = models.CharField(blank=True, null=True, max_length=100)
unit = models.CharField(blank=True, null=True, max_length=100)
unit2 = models.CharField(blank=True, null=True, max_length=100)
ingredient = models.CharField(db_column='Ingredient', blank=True, null=True, max_length=255)
class Meta:
managed = True
db_table = 'Ingredients'
class Recipe(models.Model):
recipeid = models.AutoField(db_column='RecipeID', primary_key=True, blank=True) # Field name made lowercase.
title = models.CharField(db_column='Title', blank=True, null=True, max_length=255) # Field name made lowercase.
preperation = models.TextField(db_column='Preperation', blank=True, null=True) # Field name made lowercase.
images = models.CharField(db_column='Images', blank=True, null=True, max_length=255) # Field name made lowercase.
#ingredients = models.ManyToManyField(Ingredients)
ingredients = models.ManyToManyField(Ingredients, related_name='recipes')
class Meta:
managed = True
db_table = 'Recipes'
When there is no issue it has to be in the serializer or in the view.
Serializer
class IngredientsSerializer(serializers.ModelSerializer):
# ingredients = serializers.CharField(source='ingredients__ingredients')
class Meta:
model = Ingredients
fields = ['ingredient','recipeid']
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients = IngredientsSerializer(many=True)
class Meta:
model = Recipe
fields = ['title','ingredients']
View
class FullRecipesView(generics.ListCreateAPIView):
serializer_class = FullRecipeSerializer
permission_classes = [
permissions.AllowAny
]
queryset = Recipe.objects.all()
This is at the moment my output
But I want e.g. the recipe with id 0 and all the ingredients which have also recipe id 0.
I really hope that you can help me. Thank you so much!
From the doc of ForeignKey.related_name,
If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'.
So, change the related_name of Ingredients.recipeid field to
class Ingredients(models.Model):
# rest of the fields
recipeid = models.ForeignKey(
'Recipe',
models.DO_NOTHING,
db_column='recipeid',
blank=True,
null=True,
related_name="ingredients_ref" # Changed the related name
)
Then, migrate the database using python manage.py makemigrations and python manage.py migrate
Then, update your FullRecipeSerializer class as,
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients_forward = IngredientsSerializer(many=True, source="ingredients")
ingredients_backward = IngredientsSerializer(many=True, source="ingredients_ref")
class Meta:
model = Recipe
fields = ['title', 'ingredients_forward', 'ingredients_backward']
Note that, here I have added two fields named ingredients_forward and ingredients_backward because there existing two types of relationships between Recipe and Ingredients and I am not sure which one you are seeking.
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.
I wanted to make a form which should be showing all the fields defined in models, wether the fields include a foreign key to some other class in the models. I am using ModelForm to generate forms.
My models look like
class Employee(Person):
nickname = models.CharField(_('nickname'), max_length=25, null=True,
blank=True)
blood_type = models.CharField(_('blood group'), max_length=3, null=True,
blank=True, choices=BLOOD_TYPE_CHOICES)
marital_status = models.CharField(_('marital status'), max_length=1,
null=True, blank=True, choices=MARITAL_STATUS_CHOICES)
nationality = CountryField(_('nationality'), default='IN', null=True,
blank=True)
about = models.TextField(_('about'), blank=True, null=True)
dependent = models.ManyToManyField(Dependent,
through='DependentRelationship')
pan_card_number = models.CharField(_('PAN card number'), max_length=50,
blank=True, null=True)
policy_number = models.CharField(_('policy number'), max_length=50,
null=True, blank=True)
# code specific details
user = models.OneToOneField(User, blank=True, null=True,
verbose_name=_('user'))
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('last modified'), auto_now=True)
#models.permalink
def get_absolute_url(self):
return ('contacts_employee_detail', [str(self.id)])
class Person(models.Model):
"""Person model"""
title = models.CharField(_('title'), max_length=20, null=True, blank=True)
first_name = models.CharField(_('first name'), max_length=100)
middle_name = models.CharField(_('middle name'), max_length=100, null=True,
blank=True)
last_name = models.CharField(_('last name'), max_length=100, null=True,
blank=True)
suffix = models.CharField(_('suffix'), max_length=20, null=True,
blank=True)
slug = models.SlugField(_('slug'), max_length=50, unique=True)
phone_number = generic.GenericRelation('PhoneNumber')
email_address = generic.GenericRelation('EmailAddress')
address = generic.GenericRelation('Address')
date_of_birth = models.DateField(_('date of birth'), null=True, blank=True)
gender = models.CharField(_('gender'), max_length=1, null=True,
blank=True, choices=GENDER_CHOICES)
class Address(models.Model):
"""Street Address model"""
TYPE_CHOICES = (
('c', _('correspondence address')),
('p', _('present address')),
('m', _('permanent address')),
)
address_type = models.CharField(_('address type'), max_length=1,
choices=TYPE_CHOICES)
content_type = models.ForeignKey(ContentType,
limit_choices_to={'app_label': 'contacts'})
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
street = models.TextField(_('street'), blank=True, null=True)
city = models.CharField(_('city'), max_length=200, blank=True, null=True)
province = models.CharField(_('State/UT'), max_length=200, blank=True,
null=True)
post_code = models.CharField(_('postal code'), max_length=15, blank=True,
null=True)
country = CountryField(_('country'), default='IN')
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('date modified'), auto_now=True)
So please if anyone could help me out, or suggest me some useful links from where i can get some help. Thank You!!!
Here is the documentation...
Basic usage is:
class EmployeeForm(ModelForm):
class Meta:
model = Employee
fields = ('somefield','otherfield')
etc...
fields is a optional argument, used for defining witch fields will be presented on the form... You can also override some fields using the following
class EmployeeForm(ModelForm):
otherfield = forms.CharField(...)
class Meta:
model = Employee
fields = ('somefield','otherfield')
That means, Your form is created from Employee model, "somefield" and "otherfield" will be added as form fields, and somefield will be populated directly from your model, but otherfield will be defined as if you override it in the form class...
EDIT: Overriding is used for small changes, so ,it is not right to change the data type of the field... As far as you gave the field same name, there is no problem, it will match the related model field using the name of the form field... So:
class SomeModel(Model):
somefield = CharField()
class SomeForm(ModelForm):
somefield = Charfield(Widget=...)
class Meta:
model = SomeModel
Since field names are equivalent, there is no problem...
Basic reason for overriding is, you may wish to use a widget to change the appearance of the form field(making a TextField looks like a single line Charfield) or pass some attributes (like defining cols and rows of a text field, or addng a simlpe datepicker to a datetime field. Or you may wish to use choices parameter to populate a field with value-label pairs...
You must aviod any kind of data-based changes, if you do, you might get a database level error.