Django Choices Not Being DIsplayed - django

Good day,
I am trying to create a django model that contains a choice whether the user has read or not read a book. For that I have made a choice list. But i am unable to display it on the admin panel. All other fields are getting displayed other than the choice field.
Can you please tell me where I am going wrong. I am new to django and have referred from the documnetation.
Following is the code:
class Book(models.Model):
YES = 'y'
NO = 'n'
DID_READ_CHOICES = [
(YES,'Yes'),
(NO,'No'),
]
title = models.CharField(max_length=100)
author = models.ForeignKey(
Author,
on_delete=models.SET_NULL,
null=True,
related_name='author_books'
)
genre = models.ManyToManyField(Genre, help_text='Select a genre for this book')
summary = models.TextField(max_length=1000, help_text='Enter a brief description of the book',blank=True,null=True)
read = models.CharField(
max_length=1,
choices=DID_READ_CHOICES,
default=NO,
),
objects = BookManager()
class Meta:
ordering = ['title']
def __str__(self):
return self.title
Thank you

There is a trailing question at the end of read, thus django did not detect the field.

Related

Author page in django migrations and questions

I want to make a website for eBooks with a page that has all the books published by one of the authors. The problem is that I have no idea how to do that. I will mention that I am a beginner.
I tried this int the model file
class Author(models.Model):
author = models.TextField()
class Product(models.Model):
…
author=models.ForeignKey(Author,on_delete=models.CASCADE)
The result in the terminal was:
File "/home/user/petnet/petnet-env/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 264, in check_constraints
raise IntegrityError(
django.db.utils.IntegrityError: The row in table 'store_product' with primary key '2' has an invalid foreign key: store_product.author_id contains a value 'anonim' that does not have a corresponding value in store_author.id.
I think this is caused by the act that I made the author field later and there were already authors fields from before, but then, when I tried to revert back to what I had before doing this, I got some errors regarding migrations.
Also the views were:
def author_detail(request, slug):
author = get_object_or_404(Author, slug=slug)
products = author.products.filter(status=Product.ACTIVE)
return render(request, 'store/author_detail.html', {
'author':author,
'products':products
})
But I am also curious if there is a chance I could use only this for models so I could use the form for adding a product in a much easier way.
class Product(models.Model):
DRAFT = 'draft'
WAITING_APPROVAL = 'waitingapproval'
ACTIVE = 'active'
DELETED = 'deleted'
STATUS_CHOICES = (
(DRAFT, 'Ciorna'),
(WAITING_APPROVAL, 'Asteapta aprobare'),
(ACTIVE, 'Activ'),
(DELETED, 'Sters')
)
user = models.ForeignKey(User, related_name='products',on_delete=models.CASCADE)
category=models.ForeignKey(Category, related_name='products',on_delete=models.CASCADE)
title = models.CharField(max_length=50)
image = models.ImageField(upload_to='uploads/product_images/', blank=True, null=True)
editie = models.IntegerField()
editura = models.CharField(max_length=50)
description = models.TextField(blank=True)
author = models.TextField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=50)
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default=ACTIVE)

Getting a column instead of an object when relating with PrimaryKeyRelatedField in Django-Rest-Framework

I have a model for applications, which among many attributes have a category. This category is in fact a key to another model that has the category ID, its name, and so on.
class Application(models.Model):
title = models.CharField(max_length=50)
vendor = models.CharField(max_length=50, default="Unknown", null=False)
.
.
.
category = models.ForeignKey('ApplicationCategory', related_name='applications', null=False, default=1, on_delete=models.SET_DEFAULT)
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
Then, on the Django REST serializers side I have the serializer for the applications:
class SoftwareSerializer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=ApplicationCategory.objects.all())
class Meta:
model = Application
fields = ['id', 'title', ... 'category']
Which is generating the expected API view, with a dropdown for the categories, but showing them as the ApplicationCategory objects and not giving me their name.
API showing Category dropdown with objects instead of names
Is there a way to access attributes of those objects to show the name in the dropdown, for usability sake?
I have also tried creating a CategorySerializer object (class CategorySerializer(serializers.ModelSerializer)) and then using it as category = CategorySerializer(many=False) but instead of dropdowns, I get open text fields for the attributes of the category.
Am I trying to do something that is not expected to work?
try to define the desired text in str method for your ApplicationCategory class:
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
#example
def __str__(self):
return '%s: %s' % (self.name , self.description)

Django inline model formset with 2 models

First of all, please forgive for my newbie questions. I did copy most of the code, and try to understand from Django documents.
Code as below:
models.py
class Order(models.Model):
ORDER_CHOICES = (
('import', 'IMPORT'),
('export', 'EXPORT')
)
storage = models.ForeignKey(Storage, on_delete=models.PROTECT)
order_type = models.CharField(max_length=6, choices=ORDER_CHOICES)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
class Item(models.Model):
def random_barcode():
return str(random.randint(10000000, 99999999))
type = models.ForeignKey(Type, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
item_name = models.CharField(max_length=50, help_text='Name of goods, max 50 characters')
barcode = models.CharField(max_length=8, default=random_barcode, unique=True)
production_date = models.DateField()
expired_date = models.DateField()
def __str__(self):
return self.item_type
forms.py
class ItemForm(ModelForm):
class Meta:
model = Item
exclude = ['order',]
fields = ['type', 'brand', 'item_name', 'production_date', 'expired_date']
ItemFormSet = inlineformset_factory(Order, Item, form=ItemForm, extra=1)
views.py
class CreatePO(CreateView):
model = Order
context_object_name = 'orders'
template_name = 'storages/create_po.html'
fields = ['order_type', 'storage',]
*#dun't know how to write below code....*
1st question: how to use inline formset to write the CreatePO view?
2nd question: I need my create PO template as below picture, how to add a "Quantity" field?
This kind of template need Javascript, right? Any alternative solution? I have no knowledge with javascript.
First of all, move the def random_barcode(): before def __str__(self): it looks so ugly formated code.
Then let's have a look in your pic, if you haven't proper experience with Javascript you can use Admin Views from Django, it's much more simple and supported by Django 2.1. Read more if you would like to give permission to everyone in a admin-views page https://docs.djangoproject.com/el/2.1/releases/2.1/#model-view-permission
So quantity will be just added inside Item class
quantity = models.PositiveSmallIntegerField(default=1)
Also for your form, in my opinion, you need modelform_factory, so I suggest to read this one https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/#modelform-factory-function

How to make Django forms dynamic (with clickable fields and appearing fields)

In my Django project I have the following model:
models.py
class Paper(models.Model):
title = models.CharField(max_length=500)
description = models.CharField(max_length=1500)
chapter_1 = models.CharField(max_length=50, default='Intro')
chapter_1_status = models.CharField(max_length=3, choices=[('On','On'), ('Off','Off')], blank=True, null=True)
chapter_1_description = models.CharField(max_length=1500)
chapter_1_word_count = models.IntegerField()
chapter_1_reading_time = models.DurationField(blank=True, null=True)
chapter_2 = models.CharField(max_length=50, default='Hypothesis')
chapter_2_status = models.CharField(max_length=3, choices=[('On','On'), ('Off','Off')], blank=True, null=True)
chapter_2_description = models.CharField(max_length=1500)
chapter_2_word_count = models.IntegerField()
chapter_2_reading_time = models.DurationField(blank=True, null=True)
As you can see, apart from title and description all the other fields are repetitive (chapter 1, chapter 2, chapter 3 and so on till chapter 9 which is the maximum for the assigned Paper).
I'm using the field status to check whether that chapter will actually be included in the paper or not. If someone picks Off, the chapter won't be showed in the paper.
I now need to translate this concept into something more advanced: instead of having the regular Django form for this model, I would like to have a form where users see:
title
description
a list of the chapters available (intro, hypothesis...) and when they click on the specific chapter they want to include all the fields related to that chapter appear. All the chapters that do no get selected or clicked on should be treated as if the status was Off, so they should not show.
Right now, my forms.py looks like this:
class PaperFormClass(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(PaperFormClass, self).__init__(*args, **kwargs)
for field in iter(self.fields):
self.fields[field].widget.attrs.update({
'class': 'form-control form-control-lg'
})
class Meta:
model = Paper
fields = '__all__'
class PaperForm(forms.ModelForm):
class Meta:
model = Paper
fields = '__all__'
How can I achieve a form that instead of displaying every field in model just displays title, description and a clickable list of all the chapters that can be included in the Paper? After the click on one chapter, the other fields related to that chapter should appear and be editable.
Thanks so much in advance for any suggestion that you have.
I would suggest create another model Chapter
class Chapter(models.Model):
paper = models.ForeignKey(Paper, related_name="chapters")
chapter = models.CharField(max_length=2, default='1', choices=[(i, i) for i in range(1,10)])
status = models.CharField(max_length=3, choices=[('On','On'), ('Off','Off')], blank=True, null=True)
description = models.CharField(max_length=1500)
word_count = models.IntegerField()
reading_time = models.DurationField(blank=True, null=True)
Then check for inline show as inlines

Store user specific data for each object

If you have eg an app that stores articles and each of these articles can be rated by the user. This rating is not visible to the other users and is user specific (no overall rating) ie each rating of the same article-object needs to be stored for each user.
Currently I do this complete crazy stuff:
class Article(models.Model):
text = models.TextField(null=True, blank=True)
def __unicode__(self):
return self.text
class UserArticleStorage(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null=True,
)
articles_rated_1 = models.ManyToManyField(
Article,
related_name="articles_rated_1",
blank=True
)
articles_rated_2 = models.ManyToManyField(
Article,
related_name="articles_rated_3",
blank=True
)
articles_rated_3 = models.ManyToManyField(
Article,
related_name="articles_rated_3",
blank=True
)
And I get them in the view by e.g. request.user.userarticlestorage.articles_rated_3
What is the normal way to store this user specific rating as an IntegerField?
I think you can do that by defining a simple model:
class Rating(models.Model):
article = models.ForeignKey(Article, ..., related_name='ratings')
user = models.ForeignKey(settings.AUTH_USER_MODEL,, ..., related_name='ratings')
rate = models.IntegerField()
and then access ratings by:
request.user.ratings