Attribute Error in Django model Foreign Key - django

In My Django Project, there are two apps: Login and Company
The error that am receiving in this is
AttributeError: module 'login.models' has no attribute 'Country'
Company App > models.py
from django.db import models
from login import models as LM
class CompanyProfile(models.Model):
full_name = models.CharField(max_length=255,
unique = True)
country = models.ForeignKey(LM.Country,
on_delete=models.SET_NULL,
null=True,
blank=False)
state = models.ForeignKey(LM.State,
on_delete=models.SET_NULL,
null=True,
blank=False)
def __str__(self):
return self.full_name
Login App > models.py
class Country(models.Model):
"""List of Country"""
name = models.CharField(max_length=50, unique= True, default='None')
code = models.CharField(max_length=2, unique= True, primary_key=True, default ='NA')
def __str__(self):
return str(self.code)
class State(models.Model):
"""List fo State"""
region = models.CharField(max_length = 255, unique = True, primary_key=True, default='None')
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, blank=False, default ='NA')
def __str__(self):
return self.region
Here is test to check that weather is login is getting imported or not
def test_import():
try:
# import pdb; pdb.set_trace()
importlib.find_loader('LM.Country')
found = True
except ImportError:
found = False
print(found)
Answer is received stands to be True
python3 manage.py shell
>>> test_import()
True
Now on other stackoverflow blogs i checked i thought it could be of Circlular Import
But i have already fixed that still am getting this error?
Thanks in Advance
Regards

I am not able to see any issue here technically. Maybe Django doesn't support this alias way of mentioning model as Foreign Key which I have never tried this way.
But I would suggest to use string format for adding Foreign Key of other model as below.
class CompanyProfile(models.Model):
full_name = models.CharField(max_length=255, unique = True)
# In following line, as I mention model name in string which django understands
country = models.ForeignKey('login.Country', on_delete=models.SET_NULL,
null=True,blank=False)
Another way is simple import but it might be a problem in case of circular depedencies. So I don't recommend to use that.
I hope you get the answer out of it.

Related

Django Rest Framework not validating all model's fields

I searched for this problem everywhere without being able to find an answer though it seems basic DRF usage, so I might be missing sth.
I have a Customer model with certain required fields:
from django.db import models
from django.utils.translation import gettext_lazy as _
from applications.core.models.country import Country
from applications.core.models.customer_states.customer_state import \
CustomerState
class Customer(models.Model):
class Meta:
verbose_name = _('customer')
verbose_name_plural = _('customers')
user_email = models.EmailField(_('email'), max_length=100, unique=True, default=None)
complete_name = models.CharField(_('complete name'), max_length=200, default=None)
phone = models.CharField(_('phone'), max_length=50, default=None)
country = models.ForeignKey(Country, models.PROTECT, verbose_name=_('country'), default=None)
city = models.CharField(_('city'), max_length=100, default=None)
city_state = models.CharField(_('city state'), max_length=100, default=None)
address = models.CharField(_('address'), max_length=100)
zip_code = models.CharField(_('zip code'), max_length=50, default=None)
customer_state = models.OneToOneField(CustomerState, models.PROTECT)
notes = models.TextField(_('notes'), max_length=200, blank=True, null=True)
And I have this serializer:
from rest_framework import serializers
from applications.core.models.customer import Customer
from applications.core.models.customer_states.implementations.pending_manual_validation_state import \
PendingManualValidationState
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
def to_internal_value(self, data):
self.add_default_state_if_missing(data)
return super(CustomerSerializer, self).to_internal_value(data)
#staticmethod
def add_default_state_if_missing(data):
data['customer_state'] = PendingManualValidationState.objects.create().pk
Though I have explicitly told DRF that it should use all model's fields it does not seem to check for the requirement of fields like 'address' and whenever I create the serializer with data missing 'address' and call serializer.is_valid() it returns True.
Why?
Found the answer by myself:
It would seem that default=None in the field makes DRF realize that even if the field is required, not receiving data for it is not a problem.
I set those default because otherwise Django would set a '' default value and thus, PostgreSQL would not raise exceptions for those empty data fields. But now that I am starting to use DRF for validations I no longer need those default.
Yet, if I happen to create and save a Customer without using the serializer, then I risk letting Django create a field with a default '' without having PostgreSQL complain about it. I figure that risk has a low probability though.

Django model select between two columns/fields?

I have a Slider module that i want to include items from movies_movie and shows_show table. An item can either be a show or movie. How do i make user select between movie and show? Currently i have columns for movie and show but how do i force user to select between the two?
also title_en is a column in movie or tv show tables. So the title of the movie/show selected should display in row after save.
class Slider_items(models.Model):
order = models.IntegerField(max_length=3, blank=True)
movie = models.ForeignKey('movies.movie', on_delete=models.CASCADE, blank=True)
show = models.ForeignKey('shows.show', on_delete=models.CASCADE, blank=True)
def __str__(self):
return self.title_en
class Meta:
verbose_name = "Slider Items Module"
verbose_name_plural = "Slider Item Module"
Also if a show is selected and a movie isn't, how do i know title_en will be taken from show and not movie?
I think you can do something like this:
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
class Slider_items(models.Model):
order = models.IntegerField(max_length=3, blank=True)
# don't forget to add null=True to both fields
movie = models.ForeignKey('movies.movie', on_delete=models.CASCADE, blank=True, null=True)
show = models.ForeignKey('shows.show', on_delete=models.CASCADE, blank=True, null=True)
# see docs, https://docs.djangoproject.com/en/3.2/ref/models/instances/#django.db.models.Model.clean
def clean(self):
if self.movie and self.show:
raise ValidationError({'movie': _('You can't select both types at the same time')})
elif not self.movie and not self.show:
raise ValidationError({'movie': _('You must select one type')})
def __str__(self):
return self.movie.title_en if self.movie else self.show.title_en
class Meta:
verbose_name = "Slider Items Module"
verbose_name_plural = "Slider Item Module"
You may consider using django contenttypes.
Imagine in the future, you have not just Movie, Show, but have new Class such as Book, Podcase, it might not be a good idea to keep adding new foreignkey to your Slider Model.
I have not used contenttype before, so I am referencing this SO answer.
(using python 3.6, django 3.2)
models.py
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Movie(models.Model):
title = models.CharField(max_length=50)
director = models.CharField(max_length=50)
class Show(models.Model):
title = models.CharField(max_length=50)
date = models.DateField()
class Slider(models.Model):
order = models.IntegerField(max_length=3, blank=True)
choices = models.Q(model='movie') | models.Q(model='show')
selection_type = models.ForeignKey(
ContentType, limit_choices_to=choices,
on_delete=models.CASCADE)
selection_id = models.PositiveIntegerField()
selection = GenericForeignKey('selection_type', 'selection_id')
def __str__(self):
return self.selection.title
admin.py
#admin.register(Slider)
class SliderAdmin(admin.ModelAdmin):
pass
at django shell, the following is valid.
movie = Movie.objects.create(title='movie 1', director='ben')
show = Show.objects.create(title='show 1', date='2021-01-01')
s1 = Slider.objects.create(selection=movie, order=1)
s2 = Slider.objects.create(selection=show, order=2)
However, using limit_choices_to only restrict the choices in admin page, and there is no constraint at database level. i.e. the following are actually legal.
place = Place.objects.create(name='home')
s3 = Slider.objects.create(selection=s3, order=3)
I have not found a fix for this issue yet. Maybe doing some validation in save method is a way (see the comments under this).

Django 1.11 many to many does not appear in django admin

Hi i have a django model for notification which have a many-to-many relation but nothing appears in django admin ( all fields do not appear)
class Notification(models.Model):
"""send notification model"""
title = models.CharField(max_length=200)
text = models.TextField(null=True, blank=True)
device = models.ManyToManyField(Device, null=True, blank=True)
country = models.ManyToManyField(Country, null=True, blank=True)
sent = models.BooleanField(default=False)
when i open django admin for this model and press add notification this is what happens (nothing appears)
Country and Device Code
class Device(models.Model):
"""Store device related to :model:`accounts.User`."""
user = models.OneToOneField(User, related_name='device', on_delete=models.CASCADE)
model = models.CharField(max_length=200, blank=True, null=True)
player_id = models.CharField(max_length=200, blank=True, null=True)
class Meta:
verbose_name = 'Device'
verbose_name_plural = 'Devices'
def __str__(self):
return self.model
class Country(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
Admin.py
from django.contrib import admin
from .models import Notification
admin.site.register(Notification)
Edit:
Thank you all the problem is solved
The problem was caused by some entries in device model that did have None in the model field so there was a problem displaying it correctly.
According to https://code.djangoproject.com/ticket/2169 :
When a class has a field that isn't shown in the admin interface but
must not be blank, it's impossible to add a new one. You get a cryptic
"Please correct the error below." message with no shown errors. The
error message should probably say something about a hidden field.
Now ManyToManyFields don't need null=True, try removing those statements and see if you get an improvement.
Also, try adding the Country and Device models in admin.py so admin can see them and display them.
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#working-with-many-to-many-models
Define an inline for the many-to-manys in admin.py:
from django.contrib import admin
class DeviceInline(admin.TabularInline):
model = Notification.device.through
class CountryInline(admin.TabularInline):
model = Notification.country.through
class NotificationAdmin(admin.ModelAdmin):
inlines = [
DeviceInline, CountryInline
]
exclude = ("device", "country")

Django admin site gives error on Djangae

I have a Django app that works perfectly on google app engine, using the datastore via djangae. However, the admin site throws an error:
NotSupportedError at /admin/auth/user/5629499534213120/change/
Cross-join where filters are not supported on the Datastore
This error only occurs when trying to edit the default Django user model. Not sure why this is happening.
I have used the default Django user model. (this is an app dealing with donations for a nonprofit)
models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class FoodSplashUser(models.Model):
base_user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.TextField(null=True)
city = models.TextField(null=True)
state = models.CharField(max_length=4, null=True)
zip = models.CharField(max_length=10, null=True)
def __str__(self):
return str(self.base_user.username)
class Organization(models.Model):
base_user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.TextField(null=True)
city = models.TextField(null=True)
state = models.CharField(max_length=4, null=True)
zip = models.CharField(max_length=10, null=True)
description = models.TextField(null=True)
image_url = models.URLField(null=True)
def __str__(self):
return str(self.base_user.username)
class DonationRequest(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now=True)
request_type = models.TextField(null=True)
description = models.TextField(null=True)
def __str__(self):
return str(self.organization.base_user.username) + " " + self.request_type
class DonationPromise(models.Model):
user = models.ForeignKey(FoodSplashUser, on_delete=models.CASCADE)
donation_request = models.ForeignKey(DonationRequest, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now=True)
verified = models.BooleanField(default=False)
def __str__(self):
return str(self.user.base_user.username) + " " + str(self.donation_request)
This app goes with the default Django admin interface, but I decided to make the classes below for easy editing later.
admin.py:
from django.contrib import admin
from . import models
# Register your models here.
class FoodSplashUserAdmin(admin.ModelAdmin):
pass
class OrganizationAdmin(admin.ModelAdmin):
pass
class DonationRequestAdmin(admin.ModelAdmin):
pass
class DonationPromiseAdmin(admin.ModelAdmin):
pass
admin.site.register(models.FoodSplashUser, FoodSplashUserAdmin)
admin.site.register(models.Organization, OrganizationAdmin)
admin.site.register(models.DonationRequest, DonationPromiseAdmin)
admin.site.register(models.DonationPromise, DonationPromiseAdmin)
This may be a separate error, but :
admin.site.register(models.DonationRequest, DonationPromiseAdmin)
admin.site.register(models.DonationPromise, DonationPromiseAdmin)
Shouldn't that first one be: DonationRequestAdmin?
NotSupportedError indicates that your code performs an action that is not possible with App Engine Datastore. Not all the Django ORM features can be used in a non-relational database which Datastore is. You are trying to create an entity that has some relations, which causes the error. Probably it is a good idea to use Gauth for authentication and user management, as described in the Djangae docs.

Cross Database foreign key error

This my model of first Database DB1:
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=100, null=True)
address = models.TextField(max_length=200, null=True)
website = models.CharField(max_length=200, null=True)
conatct_no = models.CharField(max_length=20, null=True)
email = models.EmailField(max_length=20, null=True)
logo = models.FileField(upload_to='logo/', blank=True, null=True)
created = models.DateTimeField('company created', auto_now_add=True)
updated = models.DateTimeField('company updated', auto_now=True, null=True)
def __unicode__(self): # Python 3: def __str__(self):
return self.name
Model of 2nd Database Db2:
from django.db import models
from leavebuddymaster.models import Company
class Department(models.Model):
company = models.ForeignKey(Company)
department_name = models.CharField(max_length=50, null=True)
created = models.DateTimeField('department created', auto_now_add=True)
updated = models.DateTimeField('department updated', auto_now=True, null=True)
def __unicode__(self): # Python 3: def __str__(self):
return self.department_name
Now when i open the Department table it gives me a error as:
ProgrammingError at /admin/leavebuddyapp/department/
(1146, "Table 'leavebuddy_master.leavebuddyapp_department' doesn't exist")
I have done all the settings in settings.py correctly for the two databases. Can you please guide me in the right direction. Thanx in advance.
You're correct, Django does not currently support foreign key relationships spanning multiple databases.
From Cross-database relations [Edit 2020: Django version bump]:
If you have used a router to partition models to different databases, any foreign key and many-to-many relationships defined by those models must be internal to a single database.
This is because of referential integrity. In order to maintain a relationship between two objects, Django needs to know that the primary key of the related object is valid. If the primary key is stored on a separate database, it’s not possible to easily evaluate the validity of a primary key.
A solution I thought up that you could try (though it may present other problems):
from leavebuddymaster.models import Company
class Department(models.Model):
company_id = models.IntegerField()
#property
def company(self):
return Company.objects.get(pk=self.company_id)
This allows you to refer to Department.company like you normally would in your example. Setting it would just be a matter of Department.company_id = Company.pk. Hope it helps, or at least inspires a better solution!