django.db.utils.IntegrityError: UNIQUE constraint failed: - python

I am making review api with django, but I have a problem.
models.py
from django.db import models
import uuid
# Create your models here.
from django.utils.text import slugify
class buildingData(models.Model):
building_name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(unique=True, default=uuid.uuid1)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
building_time = models.CharField(max_length=50)
def save(self, *args, **kwargs):
self.slug = slugify(self.building_name)
return super().save(*args, **kwargs)
class reviewData(models.Model):
building = models.ForeignKey(buildingData, related_name='reviews', on_delete=models.CASCADE, null=False, blank=False)
review_content = models.TextField()
star_num = models.FloatField()
urls.py
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
path('api/buildingdata/<slug:slug>/', ReviewListAPI.as_view())
]
I am collecting data with crawling, but...
django.db.utils.IntegrityError: UNIQUE constraint failed: crawling_data_buildingdata.slug
This error occurs.
I've tried deleting migrate file and migration again, but still doesn't work.
Is there any problem on my code or is there other way to solve this?

That is because the uuid1 is generated from your machine ID and time stamp and the machine ID in your case remains constant, that's why they look pretty similar at the end. You may use uuid4() to get a random unique UUID.
Answer from #ZdaR in this answer
You should change the first model to this:
class buildingData(models.Model):
building_name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(unique=True, default=uuid.uuid4)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
building_time = models.CharField(max_length=50)
Also you can use your slug as primary key with this:
slug = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
Edited:
I see your save function. in your save function you should remove the slug assignment. Or change it to self.slug = None. If you want to have a slug from the building name you must use TextField or CharField in the model:
slug = models.TextField(unique=True, default=uuid.uuid4)

Related

NOT NULL constraint django

I am trying to create a cart model using ForeignKey relation with User.
My mall/models.py:
from django.db import models
from django.contrib.auth.models import User
class products(models.Model):
image = models.ImageField(upload_to='products/', blank=True)
name = models.CharField(max_length=100)
detail = models.TextField(max_length=100, verbose_name='detail of product')
price = models.FloatField()
def __str__(self):
return self.name
class cart(models.Model):
item = models.OneToOneField(products, on_delete=models.CASCADE)
user = models.ForeignKey(User, null=True, blank=True, default=None, on_delete=models.CASCADE)
def __str__(self):
return self.item.name
I am getting a error like this:
django.db.utils.IntegrityError: NOT NULL constraint failed: new__mall_cart.user_id
whenever I am trying to migrate it. Its showing the same error if I am migrating the products class alone as well
.
I have provided null=True as well as blank=True and the superuser is created with the name of admin. What is issue here?

Django filter relationship in models.py

Assuming the following scenario at two seperated apps where I want to count the number of post elements of a specific category at my template:
Categories/models.py
from Posts.models import Post
...
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=20, verbose_name="Title")
...
#property
def posts(self):
return Post.objects.filter(category_id=self.id).count()
Posts/models.py
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(verbose_name="Title")
content = models.TextField(verbose_name="Content")
tag = models.CharField(verbose_name="Meta", max_length=70, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
template.html:
<h5>Number of Post elements: {{ category.posts }}</h5>
sadly this always results in the following error:
ImportError: cannot import name 'Post' from partially initialized
module 'Posts.models' (most likely due to a circular import)
This is likely because you import Posts.models in your Categories.models and vice-versa. You can import this in the property itself:
# no from Posts.models import Post
# …
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=20, verbose_name="Title")
# …
#property
def posts(self):
from Posts.models import Post
return Post.objects.filter(category_id=self.id).count()
But you do not need to import this model. Django automatically creates a relation in reverse. If you do not specify the related_name, that is modelname_set, so you can acccess this with:
# no from Posts.models import Post
# …
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=20, verbose_name="Title")
# …
#property
def posts(self):
return self.post_set.count()
Note: Python modules are normally written in snake_case, not PerlCase, so it
should be category, not Category.
You should try using the related name in your property:
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=20, verbose_name="Title")
...
#property
def posts(self):
return self.post_set.count()
Also, for the record, it seems odd to have Category and Post in separate apps. Likely they should be in a single blog app. Circular imports generally imply you have two apps that are too tightly-coupled. In this case, it should probably be just one app.
No need for that property, you can access the related objects by following the foreign key backwards. See the docs
<h5>Number of Post elements: {{ category.post_set.count }}</h5>
Or you can add a property but directly:
#property
def post_count(self):
return self.post_set.count()
And then:
<h5>Number of Post elements: {{ category.post_count }}</h5>
The hint is in the error as you do indeed have a circular import.
Posts.models.py will have from Categories.models import Category at the top as you are using it as a foreign key and as you are now using Post within the posts method of Category it will have from Posys.models import Post
You need to fix this which you can do in one of three ways depending if you have other models or methods using the Post class from within the Categories model.
If you do then you can use one of these two
Change the foreignKey to pass in a string rather than the Category object so
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(verbose_name="Title")
content = models.TextField(verbose_name="Content")
tag = models.CharField(verbose_name="Meta", max_length=70, blank=True)
category = models.ForeignKey("Category", on_delete=models.CASCADE, null=True)
Move the import from the top of Categories/models.py inside the posts method so that it imports locally
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=20, verbose_name="Title")
#property
def posts(self):
from Posts.models import Post
return Post.objects.filter(category_id=self.id).count()
If you don't, and we can't tell from what you have posted, then you can just use the ```post_set`` related name within the Category class and avoid the import at all. https://docs.djangoproject.com/en/3.0/topics/db/models/#be-careful-with-related-name-and-related-query-name
#property
def posts(self):
return self.post_set.count()
This will also fix the issue

Django UniqueConstraint

Context
I have the models AppVersion, App & DeployApp. In the AppVersion model users can upload APK files to the filesystem. I am using a pre_save signal to prevent uploading APK files with the same version_code for a specific App like this:
#receiver(pre_save, sender=AppVersion)
def prevent_duplicate_version_code(sender, instance, **kwargs):
qs = AppVersion.objects.filter(app_uuid=instance.app_uuid, version_code=instance.version_code)
if qs.exists():
raise FileExistsError("Version code has to be unique for a specific app")
This signal does what I want, except it also raises the error when I am trying to create an object in the bridge-table DeployApp.
Models
# models.py
class App(models.Model):
app_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
app_name = models.CharField(max_length=100)
class AppVersion(models.Model):
app_version_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
app_uuid = models.ForeignKey(App, on_delete=models.CASCADE, related_name='app_versions')
app_version_name = models.CharField(max_length=100)
version_code = models.IntegerField(blank=True, null=True, editable=False)
source = models.FileField(upload_to=get_app_path, storage=AppVersionSystemStorage())
class DeployApp(models.Model):
deploy_app_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
app_version = models.ForeignKey(AppVersion, on_delete=models.CASCADE)
device_group = models.ForeignKey(DeviceGroup, on_delete=models.CASCADE)
release_date = UnixDateTimeField()
My guess is that when creating an object of DeployApp the related AppVersion is also saved and thus the pre_save signal is called and raises the Exception.
I also tried to override the save() method for the AppVersion model but the results are the same.
How do I make sure that the Exception only happens upon creating a new AppVersion instance and does not happen when adding or editing a DeployApp instance?
Solved it thanks to Bear Brown his suggestion. I removed the signal and added UniqueConstraint to the AppVersion model like this:
class Meta:
db_table = 'app_version'
constraints = [
models.UniqueConstraint(fields=['app_uuid', 'version_code'], name='unique appversion')
]

Django Forms query

I have created a app using the following Model
models.py
class Vendor(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Model(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Request(models.Model):
job_reference = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.job_reference
class Device(models.Model):
Vendor = models.ForeignKey('Vendor')
Model = models.ForeignKey('Model')
device_id = models.CharField(max_length=255, unique=True, blank=True)
is_encrypted = models.BooleanField()
is_medical = models.BooleanField()
request_job_reference = models.ForeignKey('Request')
submitted = models.DateTimeField(default=timezone.now)
When i go to the admin page I can add new devices which displayed each of the fields and the "Vendor" and "Model" allows me to either select an existing entry or has a plus icon to add a new entry (which is great)
Django_Admin_form
When i create a form for my app
forms.py
from django import forms
from . models import Device
class AddDevice(forms.ModelForm):
class Meta:
model = Device
fields = ('Vendor', 'Model', 'device_id', 'is_encrypted', 'is_medical', 'submitted')
The form on my webpage display ok however there is no option to insert a new entry to "Vendor" or "Model".
Webpage Form
I have looked on other posts on here as users have had the same issue and it's been suggested to use "ModelChoiceField" but unfortunately it still doesn't make any sense to me. Either i'm completely missing something or I have setup my models in a way which is making things harder for myself.
Can anyone explain how I can go about doing this?

Django 1.6/Python 2.7 - Populate editable form from model in view/template

I am having difficulty creating a form that pre-populates with editable data from a series of models. The goal is to essentially create a visual representation of editable key value pairs to be processed later into json. The admin section would then be used to add new keys and default values for the users to edit, or to delete keys outright.
Any insight on how to do this would be very helpful, I can handle the json part myself but I am still getting started with Django and haven't been able to produce the desired results from any of the various examples I've located (perhaps I just don't know what to search for).
My application's models.py file looks like the following:
from django.db import models
import datetime
from django.utils import timezone
class Path(models.Model):
path = models.CharField(max_length=120, blank=False, null=False)
default = models.CharField(max_length=500, blank=True, null=True)
def __unicode__(self):
return self.path
class Feature(models.Model):
killswitch = models.CharField(max_length=120, blank=False, null=False)
default = models.CharField(max_length=5, blank=False, null=False)
def __unicode__(self):
return self.killswitch
class Other(models.Model):
category = models.CharField(max_length=120, blank=False, null=False)
default = models.CharField(max_length=120)
def __unicode__(self):
return self.category
Any help, tips, or advice is GREATLY appreciated.
Thanks!

Categories

Resources