Django Mezzanine - Simple custom Admin Form - django

I need to add job offers section to my company site (as a intro to django for me). The problem is that when i inherit my model from mezzanine's Page model it adds to admins create form all bunch of field which i dont need (like publish dates, draft field, comment field etc). I want to make create/edit job offers form as simple as possible.
I tried to inherit it from basic models.Model but it throws an error ...
Unknown column 'project_joboffer.id' in 'field list'"
I tried to customize Admin Form but im still getting error above.
models.py
class JobOffer(models.Model):
title = models.CharField(max_length=255, null=False, blank=False)
place = models.CharField(max_length=255, null=True, blank=True)
date = models.DateTimeField(auto_now_add=True)
content = models.TextField(blank=False,null=False)
published = models.BooleanField(default=True)
deleted = models.NullBooleanField()
forms.py
from django import forms
from ckeditor.widgets import CKEditorWidget
from models import JobOffer
class JobOfferForm(forms.ModelForm):
title = forms.CharField(max_length=255, required=True)
place = forms.CharField(max_length=255, required=False)
content = forms.CharField(required=True , widget=CKEditorWidget())
published = forms.BooleanField(initial=True)
deleted = forms.NullBooleanField()
# class Meta:
# model = JobOffer
admin.py
class JobOfferAdmin(admin.ModelAdmin):
form = JobOfferForm
admin.site.register(JobOffer, JobOfferAdmin)

OK, i fixed it. Migrations creating and deleting wasnt enough. I dont know why but this time i had to also delete entry in django_migrations table.

Related

Test a data migration ManyToMany in Django

I tried to add a field to my ManyToMany relationship models in Django.
So step by step, I created the new model and apply makemigrations and migrate.
I checked I have the new table in my postgresql database.
Now before I will add the through keyword in the ManyToMany field I want to write a function in the migration file that will copy the old data of the previous ManyToMany table to the new one with the additional field.
I followed a solution explained here:
Django migration error :you cannot alter to or from M2M fields, or add or remove through= on M2M fields
I want to test the function that will migrate the data in a test function but I don't understand what to do.
here my code:
survey/models:
class Survey(BaseModel):
name = models.CharField(max_length=256, help_text='Survey name')
user = models.ManyToManyField(User, blank=True, help_text='patient')
survey/models:
class SurveyStatus(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
survey_status = models.CharField(max_length=10,
blank=True,
null=True,
choices=STATUS_SURVEY_CHOICES,
)
The function I wrote that need to copy the data from the previous M2M to the new one is the following one:
def create_through_relations(apps, schema_editor):
Survey = apps.get_model('survey', 'Survey')
SurveyStatus = apps.get_model('survey', 'SurveyStatus')
for survey in Survey.objects.all():
for user in survey.user.all():
SurveyStatus(
user=user,
survey=survey,
survey_status='active'
).save()
I don't understand what is apps? because it is not recognized by python
I don't understand why i need schema_editor because it's not used
it doesn't recognized my Survey or SurveyStatus models too
when i tried to run this script with
if __name__ == "__main__":
create_through_relations(survey)
I've got this error
NameError: name 'survey' is not defined
and if i tried this function
from django.apps import apps
def create_through_relations():
Survey = apps.get_model('survey', 'Survey')
SurveyStatus = apps.get_model('survey', 'SurveyStatus')
for survey in Survey.objects.all():
for user in survey.user.all():
SurveyStatus(
user=user,
survey=survey,
survey_status='active'
).save()
when i tried to run this script with
if __name__ == "__main__":
create_through_relations()
I've got this error
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
If someone can help and explain me how to solve.thanks
1: Apps represent the different parts of your project (Django Apps)
2: You don't need it at this point. In general, it translates the models into SQL syntax.
3: python manage.py <...> does load the models for execution. Your file is trying to access data that isn't available that way.
4: The variable survey can't be found in python's main function, since you never declared it there. You need to trigger it inside your project.
5: You can test things by creating a test.py (Django Tests)
6: You don't need to transfer the data to a whole new table after changing a model, just extend the existing one and migrate the changes:
class BaseModel(models.Model):
created = models.DateTimeField('created', default=timezone.now)
changed = models.DateTimeField('changed', default=timezone.now, blank=True, null=True)
class Survey(BaseModel):
uuid = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=256, help_text='Survey name')
description = models.TextField('description', blank=True)
status = models.BooleanField(default=False) # paused/ active
class SurveyQuestion(BaseModel):
survey = models.ForeignKey(Survey, related_name='survey', on_delete=models.CASCADE)
text = models.CharField(max_length=256)
# 1 -> Text, # Integer, # ChoiceField, etc.
requested_result = models.IntegerField(default=0)
class QuestionResult(BaseModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
question = models.ForeignKey(SurveyQuestion, related_name='survey_question', on_delete=models.CASCADE)
answer = models.CharField(default='', max_length=256)

How can one replicate Django admins add new row functionality?

I am looking for a way to implement the "add new model_name" functionality from Django admin to normal form in templates, i.e; outside of Django admin, how could I use the same functionality.
How could I achieve it?
The first Step is to create Business Module inside models.py
class Business(models.Model):
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'business'
verbose_name_plural = 'business'
def __str__(self):
return self.name
Then use python manage.py migrate to migrate module inside your database.
Now open admin.py file and register this Module,
from .models import Business
# Register your models here.
class BusinessAdmin(admin.ModelAdmin):
list_display = ['name', 'slug']
prepopulated_fields = {'slug': ('name',)}
admin.site.register(Business,BusinessAdmin)
Now check your Django admin panel. It will show you New Business Module there with Add, remove feature using Form.
I hope this will helpful for you.

How to save a table entry in django

I am working on a django admin based project now i am stuck with a big thing.i want to add a field named "item_issued" in the user_profile model.
in the "item issued" field there is a table which consist of 3 column "item_name","quantity" and "price".I am unable to apply this.Can u guys please help me in this?
Thanks in advance
If I understand you correctly you want to add a ForeignKey to your user_profile pointing to item_issued. You can accomplish that by creating a new model ItemIssued with the fields you mentioned:
class ItemIssued(models.Model):
item_name = models.CharField(max_length=100)
quantity = models.IntegerField()
price = models.FloatField()
Now, when you're having ItemIssued model you can add a ForeignKey to user_profile (I assume the model is called UserProfile):
class UserProfile(models.Model):
... # your existing fields
item_issued = models.ForeignKey(ItemIssued)
After that, don't forget to run
python manage.py makemigrations app
python manage.py migrate
Here is a starting point:
models.py:
class ItemIssued(models.Model):
item_name = models.CharField(max_length=50)
quantity = models.IntegerField()
models.DecimalField(max_digits=6, decimal_places=2) #use decimal field for price values.
class UserProfile(models.Model):
# some other fields..
issued_items = models.ManyToManyField("ItemIssued", related_name="+issued_items", null=True, blank=True)
And if you need to use this field outside of Django Admin, views.py:
user = UserProfile.objects.get(username="ali")
new_issued_item = ItemIssued.objects.get(item_name="test_item")
user.issued_items.add(new_issued_item) #add
user.issued_items.delete(new_issued_item) #delete
items = user.issued_items.all() # get all issued items of user
i didn't test the code. But they should work.

Many-To-Many Fields View on Django Admin

Basically I am trying to recreate a fields in this model that is similar to django user authenticate system, for this I try using many-to-many fields but it ended up like this.
I am trying to have another field that can show what exist and another field for I have chosen similar to django admin, which looks like this.
This is my code
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
class BlogPage(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=128)
preview = models.TextField(max_length=256)
content = models.TextField()
I believe what you want is a filter_horizontal widget used in the Admin template. This should help: Django Admin ManyToManyField
currently i am able to display many to many fields is admin panel
models.py
class Abc(models.Model):
course = models.ManyToManyField(Course, blank=True)
admin.py
class AbcsAdmin(admin.ModelAdmin):
"""
Admin panel management for Alumni
"""
list_display = ["id","get_course"]
def get_course(self,obj):
return [course.name for course in obj.course.all()]

Django models with OneToOne relationships?

Let's say I'm using the default auth.models.User plus my custom Profile and Address models which look like this:
class Profile(models.Model):
user = models.OneToOneField(User)
primary_phone = models.CharField(max_length=20)
address = models.ForeignKey("Address")
class Address(models.Model):
country = CountryField(default='CA')
province = CAProvinceField(default='BC')
city = models.CharField(max_length=80)
postal_code = models.CharField(max_length=6)
street1 = models.CharField(max_length=80)
street2 = models.CharField(max_length=80, blank=True, null=True)
street3 = models.CharField(max_length=80, blank=True, null=True)
Now I want to create a registration form. I could create a ModelForm based on User but that won't include fields for the Profile and Address (which are required). So what's the best way to go about building this form? Should I even use ModelForm at all?
Furthermore, how would I use the same form for editing the complex object? I could easily pass an instance of Profile back to it, which holds references to the necessary Address and Profile objects, but how do I get it to fill in the fields for me?
What about using 3 separate ModelForm. One for Address, one for User, and one for Profile but with :
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ('user', 'address',)
Then, process these 3 forms separately in your views. Specifically, for the ProfileForm use save with commit=False to update user and address field on the instance :
# ...
profile_form = ProfileForm(request.POST)
if profile_form.is_valid():
profile = profile_form.save(commit=False)
# `user` and `address` have been created previously
# by saving the other forms
profile.user = user
profile.address = address
Don't hesitate to use transactions here to be sure rows get inserted only when the 3 forms are valid.
You should look into the officially recommended way to extend the User model first, as seen in the docs, which I believe comes directly from the project manager's personal blog about the subject. (The actual blog article is rather old, now)
As for your actual issue with forms, have a look at the project manager's own reusable django-profiles app and see if perusing the code solves your issue. Specifically these functions and the views in which they are utilized.
Edited to Add:
I've looked into it a bit (as I needed to do so myself). It seems something like so would be sufficient:
# apps.profiles.models
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
...
birth_date = models.DateField(blank=True, null=True)
joined = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'user profile'
verbose_name_plural = 'user profiles'
db_table = 'user_profiles'
class Address(models.Model):
user = models.ForeignKey(UserProfile)
...
# apps.profiles.forms
from django import forms
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from django.contrib.auth.models import User
from apps.profiles.models import UserProfile, Address
class UserForm(ModelForm):
class Meta:
model = User
...
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
...
AddressFormSet = inlineformset_factory(UserProfile, Address)
I was using "..." to snip content in the code above. I have not yet tested this out but from looking through examples and the documentation on forms I believe this to be correct.
Note I put the FK from the Address model to the UserProfile and not the other way around, as in your question. I believe the inline formsets need this to work correctly.
Then of course in your views and templates you will end up treating UserForm, UserProfileForm, and AddressFormSet separately but they can all be inserted into the same form.
I think your are looking for inline formsets with model forms. This helps you to deal with multiple forms on one page and also takes care of foreign key relations.
Update:
Maybe this question helps you too: Django: multiple models in one template using forms