Django UNIQUE constraint - django

Django UNIQUE constraint failed error
django.db.utils.IntegrityError: UNIQUE constraint failed while I am using the unique together constraint in the models.
How can I use it properly?
While I am entering the data for the same publisher same issue same version number but different copy number I am getting the above error.
Is this the correct way to implement it??
class Book(models.Model):
publisher = models.IntegerField()
issue = models.CharField(max_length=255)
class Meta:
unique_together = ("publisher", "issue")
def __str__(self):
return "%s-%r" % (self.publisher,self.issue)
class Version(models.Model):
book = models.ForeignKey(Book, on_delete = models.CASCADE)
number = models.CharField(max_length=255)
book_name = models.CharField(max_length=255)
cover = models.ImageField(null=True)
description = models.CharField(max_length=255)
class Meta:
unique_together = ("book", "number")
def __str__(self):
return "%s %s" % (self.number, self.book)
class Copy(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, on_delete=models.CASCADE)
version = models.ForeignKey(Version, on_delete = models.CASCADE)
number = models.IntegerField()
book_id = models.AutoField(primary_key=True)
book_size = models.CharField(null=True, blank=True,max_length=255)
def __str__(self):
return "%r" % (self.book_id)
class Meta:
unique_together = ("version", "number")

Related

how to use django Serializer or signal to add object in database?

I create ticket , ticketflow , ticketstate , tickettype models
i need a serializer or signal that when user create ticket programmatically add ticketflow object and set state of ticket to submited or something else
Here is my models
class TicketType(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class TicketState(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class Ticket(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4 , editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket_type = models.ForeignKey(TicketType,on_delete=models.CASCADE , default=1)
title = models.CharField(max_length=255, blank=False, null=False)
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
class TicketFlow(models.Model):
uuid = models.UUIDField(default=uuid4, editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket = models.ForeignKey(Ticket,on_delete=models.CASCADE , related_name='ticketflow')
ticket_state = models.ForeignKey(TicketState,on_delete=models.CASCADE , default=1 , related_name='ticketstate')
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now= True)
class Meta:
ordering = ['-created_on']
here is my serializers
class TicketTypeSerializer(serializers.ModelSerializer):
class Meta:
model = TicketType
fields = ('id','title',)
class TicketStateSerializer(serializers.ModelSerializer):
class Meta:
model = TicketState
fields = ('id','title',)
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = ['id' , 'author', 'ticket_type','title' ,'message' , 'attachment' , 'created_on']
class TicketFlowSerializer(serializers.ModelSerializer):
class Meta:
model = TicketFlow
fields = ['author', 'ticket_state', 'message', 'attachment', 'created_on', 'updated_on']
It'll be great if someone can help me out in this. how can i create signal or override create method in serializers
You probably want your "state" field to be read-only in the serializer, this way it can only be changed programmatically, and in the model set a default value with default='pending'.
Then you can override the update method in a Serializer (see the doc here):
def update(self, instance, validated_data):
validated_data['state'] = 'edited'
return super(MySerializer, self).update(instance, validated_data)

labeling in Django Admin

I am new to Django and still learning, I have created a database and some models but I got stuck with meaningful labels in Django Admin. This is the model:
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
product_name = models.CharField(max_length= 50)
brand_name = models.CharField(max_length = 20)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
min_order = models.IntegerField()
max_order = models.IntegerField()
units = models.IntegerField()
quantity = models.ForeignKey(Quantity, on_delete=models.SET_NULL, null=True)
objects = ProductManager()
class Meta:
verbose_name = "Product"
verbose_name_plural = 'Products'
And I get this:
I want Product object (3) to be replaced byt the product_name. Thank you in advance!
You can override the __str__ method [python-doc] and return the product_name instead:
class Product(models.Model):
# …
def __str__(self):
return self.product_name

DRF need values instead of ID

This is my serializer class
class ProjectSerializer(ModelSerializer):
class Meta:
model = Project
exclude = ['deleted_at']
This is Models.py
class MandatoryFields(SoftDeletionModel):
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="%(app_label)s_%(class)s_created",null=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="%(app_label)s_%(class)s_updated",null=True)
created_date = models.DateTimeField(auto_now_add=True,null=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Project(MandatoryFields, Model):
project_name = models.CharField(max_length=255, blank=True)
project_areas = models.CharField(max_length=255, blank=True)
project_manager = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True,
related_name="%(app_label)s_%(class)s_project_manager")
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
REQUIRED_FIELDS = []
def __str__(self):
return self.project_name
I am getting Id's for the foreign keys created_by,updated_by,project_manager .But I need the values instead of Id.
for example I am getting
created_by : 1
But I need
created_by: Alex
I have tried the following
class ProjectSerializer(ModelSerializer):
created_by = SlugRelatedField(read_only=True, slug_field='created_by')
class Meta:
model = Project
exclude = ['deleted_at']
But I am getting null values.
I think that's achievable by specifying source attribute for serializer field
Somthing like this:
class ProjectSerializer(ModelSerializer):
created_by = CharField(source="created_by.first_name")
class Meta:
model = Project
exclude = ['deleted_at']
Reference : https://www.django-rest-framework.org/api-guide/fields/#source

Django join unmanaged tables

I have a four models which each contains their own data. The models are:
Category (contains department_id foreign key)
Department (contains data, no foreign key)
ProductCategory (join table containing only product_id and category_id)
Product (contains data with no foreign key)
# models.py (excluded the rest for brevity)
from django.db import models
class Department(models.Model):
department_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000, blank=True, null=True)
class Meta:
managed = False
db_table = 'department'
class Category(models.Model):
category_id = models.AutoField(primary_key=True)
#department_id = models.IntegerField()
department = models.ForeignKey(Department, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000, blank=True, null=True)
class Meta:
managed = False
db_table = 'category'
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
price = models.DecimalField(max_digits=10, decimal_places=2)
discounted_price = models.DecimalField(max_digits=10, decimal_places=2)
image = models.CharField(max_length=150, blank=True, null=True)
image_2 = models.CharField(max_length=150, blank=True, null=True)
thumbnail = models.CharField(max_length=150, blank=True, null=True)
display = models.SmallIntegerField()
class Meta:
managed = False
db_table = 'product'
class ProductCategory(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
class Meta:
managed = False
db_table = 'product_category'
unique_together = (('product', 'category'),)
From my endpoint, I need to get all products in a department and return the response in the following format:
​"rows"​: [
{
​ "product_id"​: ​integer​,
"name"​: ​string​,
​"description"​: ​string​,
"price"​: ​string​,
​"discounted_price"​: ​string​,
"thumbnail"​: ​string​
}
]
This is the endpoint:
path('products/inDepartment/<int:department_id>/', ProductViewSet.as_view({"get": "get_products_by_department"}))
How can I go about doing this? I'm stuck with the code below:
# products.py
def get_products_by_department(self, request, department_id):
"""
Get a list of Products of Departments
"""
categories = Category.objects.filter(department_id=department_id).values('category_id')
for item in categories:
category_id = item['category_id']
products = ProductCategory.objects.filter(category_id=category_id).values(
'product_id', name=F('product__name'), description=F('product__description'),
price=F('product__price'), discounted_price=F('product__discounted_price'), thumbnail=F('product__thumbnail'))
# Return response
if products.exists():
return Response(products, 200)
else:
return Response(products, 204)
The code above works and gives me the correct response but I'm not sure if I'm doing the query correctly? Should I be using a loop or is there a Django way to do it better without a loop?
Django's ORM allows for reverse relationship lookup.
https://docs.djangoproject.com/en/2.2/topics/db/queries/#lookups-that-span-relationships
categories = Category.objects.filter(department_id=department_id)
products = Product.objects.filter(productcategory__category__in=categories)

I am getting invalid keyword argument while posting product array in customer order. What should i do?

First i was getting an error like to create an explicit create method while serializing an array of product. So i added it but stiil im getting thhis error :
TypeError: 'customerorder' is an invalid keyword argument for this function
This is my serializers.py
class ProductSerializer(serializers.ModelSerializer):
product_id = serializers.IntegerField(required=False)
class Meta:
model = Product
fields = '__all__'
class CustOrderSerializer(serializers.ModelSerializer):
price = serializers.SlugRelatedField(slug_field='price', queryset=Price.objects.all())
# product = serializers.SlugRelatedField(slug_field='product', queryset=Product.objects.all())
area = serializers.SlugRelatedField(slug_field='address', queryset=Area.objects.all())
city = serializers.SlugRelatedField(slug_field='city', queryset=City.objects.all())
product = ProductSerializer(many=True)
class Meta:
model = CustOrder
fields = '__all__'
def create(self, validated_data):
product = validated_data.pop('product')
customerorder = CustOrder.objects.create(**validated_data)
for product in product:
Product.objects.create(**product, customerorder= customerorder)
return customerorder
This is models.py
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
product = ArrayField(models.CharField(max_length=200, blank=True))
def __str__(self):
return str(self.product)
class CustOrder(models.Model):
Customer_id = models.AutoField(primary_key=True)
CustomerName = models.CharField(max_length=200)
email = models.EmailField(max_length=70,blank=True, null= True, unique= True)
gender = models.CharField(max_length=6, choices=GENDER_CHOICES)
phone = PhoneField(null=False, blank=True, unique=True)
landmark = models.PointField()
#landmark = models.TextField(max_length=400, help_text="Enter the landmark", default='Enter landmark')
houseno = models.IntegerField(default=0)
#product_name = models.CharField(max_length=200, choices=PRODUCT_CHOICES,default='Boneless chicken')
# product_id = models.ForeignKey(Product, on_delete=models.CASCADE,related_name='custorder_productid')
product = models.ManyToManyField(Product, blank=True,related_name='pricetag')
quantity = models.IntegerField(default=0)
# price_id = models.ForeignKey(Price)
price = models.ForeignKey(Price, on_delete=models.SET_NULL, null=True,related_name='pricetag')
#price = models.DecimalField(max_digits=50, decimal_places=5, default=48.9)
pay_method = models.CharField(max_length=200,choices=PAYMENT_CHOICES, default='RAZOR PAY')
city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
area = models.ForeignKey(Area, on_delete=models.SET_NULL, null=True)
# Price.objects.aggregate(Sum('price'))
def __str__(self):
return self.CustomerName
There are several errors here.
Firstly for some reason you've set the related name from Product back to CustOrder as pricetag. That name does not appear to relate to either side of the relationship, so not sure why you've used it.
However even with that change, it still won't work, because you can't set many-to-many relationships at create time. You would need to create the product and then add it to the order.
But that still makes no sense, because you don't actually want to be creating products at all here; you want to add existing products to the order. So just do that:
customerorder = CustOrder.objects.create(**validated_data)
customerorder.product.add(*product)
Your Product model has not field customerorder. That is the reason why Django raises the error.