Create multiple related objects in Django Admin - django

I am using Django 2.0
I have two models
class Chapter(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
name = models.CharField(max_length=250, blank=False)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
class META:
verbose_name_plural = 'chapters'
db_table = 'chapters'
def __str__(self):
return self.name
class ChapterQuestion(models.Model):
chapter = models.ForeignKey(Chapter, on_delete=models.CASCADE)
word = models.CharField(max_length=250)
definition = models.CharField(max_length=250)
class META:
verbose_name_plural = 'chapter questions'
db_table = 'chapter_questions'
def __str__(self):
return self.word
Since Each ChapterQuestion belongs to only one Chapter, I think it could be Many-to-one relation.
My admin.py contain only
admin.site.register(Chapter)
admin.site.register(ChapterQuestion)
I want to be able to add/edit multiple questions while creating/editing chapter using Django Admin.
But Django Admin is showing only chapter fields
Also, I want created_by column to be field automatically by logged in user and remove from form.

You need to use inline forms
class ChapterQuestionInline(admin.StackedInline):
model = ChapterQuestion
#admin.register(Chapter)
class ChapterAdmin(admin.ModelAdmin):
list_display = ["course","name","created_by"]
inlines = [ChapterQuestionInline]

Related

How to show only objects those are not selected in Django admin panel referred by Foreign Key?

In the article, when I add some product, it should not show again while adding a second one. Is there any way to do it?
I have the following models :
class Article(models.Model):
title = models.CharField(max_length=150, null=True, blank=True)
class Product(models.Model):
name = models.CharField(max_length=150, null=True, blank=True)
class ArticleProduct(models.Model):
class Meta:
unique_together = ('article', 'product')
article = models.ForeignKey(Article, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
In admin.py :
class ArticleProductIngredientInline(admin.StackedInline):
model = ArticleProduct
autocomplete_fields = ['product']
extra = 0
class ArticleAdmin(admin.ModelAdmin):
inlines = [ArticleProductIngredientInline]
search_fields = ['category', ]
class Meta:
model = Article
#admin.register(ArticleProduct)
class ArticleProductAdminModel(admin.ModelAdmin):
autocomplete_fields = ['product', 'article']
class ProductAdminModel(admin.ModelAdmin):
search_fields = ['product', ]
admin.site.register(Product, ProductAdminModel)
admin.site.register(Article, ArticleAdmin)
I have set the Article and Product field unique in ArticleProudct Model. In the Article model Even if have selected Product 1, while adding second or third products, the first product not be displayed as it is already selected.

How to add Category while adding product in Django form? Just like the Django admin form

So I am trying to build an inventory system.
I have 2 models, Categories and Product connected through the ManyToMany field.
I want to add a category while I am adding the product just like it happens in the Django admin form.
How can I do that?
My model.py File
class Categories(models.Model):
name = models.CharField(max_length=30)
organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
def __str__(self):
return f"{self.name}"
class Product(models.Model):
category = models.ManyToManyField(Categories)
brand = models.CharField(max_length=20)
model = models.CharField(max_length=20)
hac = models.CharField(max_length=20, null=True, blank=True)
rate = models.DecimalField(max_digits=6, decimal_places=2)
stock = models.IntegerField(default=0)
# organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
date_added = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.brand} {self.model} "
My form.py file
class ProductModelForm(forms.ModelForm):
class Meta:
model = Product
fields = '__all__'
**My code output **
See the below screenshots to understand what I want to do. I basically want that plus button option to add a category from the product form itself.
You should show snippets of codes that we need to provide an answer.

django abstract model to have slugfield

I want all my models to have SlugField however it seems like its not a DRY principle for each and every model to have:
slug = models.SlugField(max_length=50)
I want to implement this as follows:
Base Model
class BaseModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, unique=True)
class Meta:
abstract = True
Company Model
class Company(BaseModel):
code = models.CharField(max_length=2, primary_key=True)
name = models.CharField(max_length=50)
class Meta:
verbose_name_plural = 'Companies'
def __str__(self):
return self.name
My other models will inherit BaseModel to have those fields inherited however, whenever I save new record, SlugField is empty. Anyone could enlighten me on this please!

How to display category name on article model?

I want to render category field on an article in terms of its name(choice). Currently, it is rendered as an Id. Also, I want to be able to update the article model by entering category name(choice) instead of its Id(I am currently doing this). How can I go about implementing this?
This is what I have so far.
Models
class Category(models.Model):
"""
Model for Category
"""
CATEGORY_CHOICES = (
('Sports', 'Sports'),
('Music', 'Music'),
('Drama', 'Drama'),
('Money', 'Money'),
('Movies', 'Movies'),
('Cars', 'Cars'),
('General', 'General'),
)
name = models.CharField(max_length=30, choices=CATEGORY_CHOICES, default='General',null=False, blank=True)
def __str__(self):
return self.name
class Article(models.Model):
"""
Model for an Article
"""
title = models.CharField(max_length=255, null=False, blank=False)
description = models.TextField(null=False, blank=False)
body = models.TextField(null=False, blank=False,)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
Serializers
class ArticleSerializer(serializers.ModelSerializer):
"""
Serializer for Article.
"""
class Meta:
model = Article
fields = ('title','description','body',''category')
class CategorySerializer(serializers.ModelSerializer):
"""
Serializer for Category.
"""
class Meta:
model = Category
fields = ('name',)
Current output
Expected output
You can change your ArticleSerializer to have the category field as a CharField with a source attribute:
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.CharField(source='category.name')
class Meta:
model = Article
fields = ('title','description','body',''category')
To be able to update the Article's category via the name, you have to make sure that name is a unique field for Category. If yes, then you can use a SlugRelatedField.
category = serializers.SlugRelatedField(slug_field='name')

Create relationship between two models using django class based views

I have two models Company and Campaign. I need to create a relationship between them. I think my models are fine.
companies/model.py
class Company(models.Model):
class Meta:
verbose_name_plural = "companies"
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(blank=False, max_length=128, default='')
slug = models.SlugField(blank=True, unique=True)
archived = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
campaigns/models.py
class Campaign(models.Model):
class Meta:
verbose_name_plural = "campaigns"
company = models.ForeignKey('companies.Company', on_delete=models.CASCADE,)
title = models.CharField(blank=False, max_length=128, default='')
slug = models.UUIDField(default=uuid.uuid4, blank=True, editable=False)
def __str__(self):
return str(self.title)
campaigns/forms.py
class CampaignForm(forms.ModelForm):
class Meta:
model = Campaign
fields = ['title','description','archived']
campaigns/views.py
class CampaignCreateView(SubmitBtnMixin, CreateView):
model = Campaign
company = None
form_class = CampaignForm
submit_btn = "Add Campaign"
template_name = "form.html"
campaigns/urls.py
url(r'^campaign/create/$', CampaignCreateView.as_view(), name='campaign-create'),
My question is, when creating a new campaign, where and how do I pick up the Company pk to populate the Campaign model? What is the most secure and best practice for doing this?
I found a solution but would like input on best practices still.
I added this to my CampaignCreateView
def form_valid(self, form):
company = get_object_or_404(Company, id=self.kwargs.get('pk'), user_id=self.request.user.id)
form.instance.company_id = company.id
return super(CampaignCreateView, self).form_valid(form)
and I changed my url to:
url(r'^campaign/(?P<pk>\d+)/create/$', CampaignCreateView.as_view()...
Not sure that I like the pk in the URL since it can be jacked. This is why I am filtering on the userid at the company model to make sure that the data is coming from the owner.
I thought of doing this by registering the company in the session id but I am not convinced that sessions do not present their own problems.