I have some models like this:
class Category(models.Model):
class Meta:
ordering = ['name']
name = models.CharField(max_length=100)
text = models.TextField(blank=True)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Tool(models.Model):
name = models.CharField(max_length=30, null=True, default='')
url = models.URLField(max_length=250, null=True, default='')
image_url = models.URLField(max_length=250, null=True, default='', blank=True)
about = models.TextField(default='', null=True, blank=True)
tags = models.ManyToManyField( Tag, related_name="tools" , blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True, related_name="category1")
altcategory = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True, related_name="category2")
And everything seem ok, except when I go to add a tag to a Tool in the Admin screens.
I can create a Tool and Tag but when I select a tag in the taglist in the Admin screens and Save I get:
The above exception (syntax error at or near "ON" LINE 1: ...ls_tool_tags" ("tool_id", "tag_id") VALUES (1, 2) ON CONFLIC... ^ ) was the direct cause of the following exception:
with the sql:
('INSERT INTO "tools_tool_tags" ("tool_id", "tag_id") VALUES (%s, %s) ON '
'CONFLICT DO NOTHING')
The DEBUG screen is saying the error is at "tag_id", is strange...
I hope it's not a version thing, since I'm using Heroku and have been really impressed with how everything "just works". My Django version is '3.0.4' and Postgres 12.2.
I don't think ManyToMany works out of the box.
So I had to create a "through" model... and change the admin form to this...
models.py
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.auth.models import User
from django.utils.html import format_html
from django.contrib.contenttypes.models import ContentType
class Category(models.Model):
class Meta:
ordering = ['name']
name = models.CharField(max_length=100)
text = models.TextField(blank=True)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Tool(models.Model):
name = models.CharField(max_length=30, null=True, default='')
url = models.URLField(max_length=250, null=True, default='')
image_url = models.URLField(max_length=250, null=True, default='', blank=True)
about = models.TextField(default='', null=True, blank=True)
tags = models.ManyToManyField(
Tag,
through="PageTags",
through_fields=('tool', 'tag'))
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True, related_name="category1")
altcategory = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True, related_name="category2")
def _get_thumbnail(self):
return format_html(u'<img src="{}" width="150"/>', self.image_url)
_get_thumbnail.allow_tags = True
def _get_link(self):
return format_html(u'<a href="{}" target="_blank"/>{}</a>', self.url, self.url)
_get_link.allow_tags = True
def __str__(self):
return self.name + ": " + self.url
class PageTags(models.Model):
tag = models.ForeignKey(Tag , on_delete=models.CASCADE, )
tool= models.ForeignKey(Tool , on_delete=models.CASCADE, )
amount = models.IntegerField(default=0)
... and admin.py to this...
from django.contrib import admin
from django.contrib.admin import TabularInline
#from django.contrib.contenttypes.admin import GenericTabularInline
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe
from .models import Tool, Category, Tag, PageTags
class PageTagsInline(admin.TabularInline):
model = PageTags
extra = 1
class ToolAdmin(admin.ModelAdmin):
#fields = ('name', )
list_display = ('name','_get_link','category','altcategory', "_get_thumbnail", )
list_filter = ('category',)
search_fields = ['name', "about"]
filter_horizontal = ('tags',)
inlines = [PageTagsInline,]
admin.site.register(Tag)
admin.site.register(Category)
admin.site.register(Tool, ToolAdmin)
And the interface is different, not like the permissions widgets, but OK... at least not bombing the admin.
Related
I'm starting a project in django 4.1. and I run into this problem:
many to many relationship: I have a field of this type that is required, and everything is fine, but when I use the filter_horizontal it does not let me insert the chosen value, it tells me that it is required, however I am selecting values
Admin.py:
from django.contrib import admin
from .models import *
from django.contrib.auth.models import User
class CatalejoAdmin(admin.ModelAdmin):
filter_horizontal = ('tematicas',)
admin.site.register(Catalejo, CatalejoAdmin)
admin.site.register(Tematicas)
Model:
from django.db import models
from django.contrib.auth.models import User
class Tematicas(models.Model):
tematica = models.CharField(max_length=500)
fecha = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User,null=True , default=User, editable=False, on_delete=models.DO_NOTHING)
class Meta:
ordering = ["tematica"]
verbose_name_plural = "Temática"
def __str__(self):
return self.tematica
class Catalejo(models.Model):
fecha = models.DateField()
titulo = models.CharField(max_length=500)
tematicas = models.ManyToManyField(Tematicas, related_name='Temáticas')
author = models.ForeignKey(User,null=True , default=User, editable=False, on_delete=models.DO_NOTHING)
fichero = models.FileField(upload_to='gestores/%Y/%m/%d', null=True, blank=True)
class Meta:
ordering = ["fecha"]
verbose_name_plural = "Catalejo"
def Tematicas(self):
return ",\n".join([p.tematica for p in self.tematicas.all()])
def dehydrate_full_title(self, Tematicas):
return '%s by %s' % (Tematicas.tematica)
enter image description here
UserProfile table: (Extended table of default User)
from django.db import models
from django.contrib.auth.models import User
from django.db.models.deletion import CASCADE`enter code here`
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=CASCADE)
k_name = models.CharField(max_length=100, default="krishok Name", null=True)
k_address = models.CharField(max_length=300, default="Goes Krishok Address Here", null=True, blank=True)
k_national_id_no = models.CharField(default="1", max_length=50)
k_phone = models.CharField(default="01778956098", max_length=20)
k_email = models.EmailField(default="xxx#gmail.com", max_length=254)
k_image = models.ImageField(default = '', upload_to = 'upload/pkrishokImage/')
national_id = models.ImageField(default= '',upload_to = 'upload/IDImage/')
Product model code:
from Store.models.userprofile import UserProfile
from django.db import models
from .categories import Category
from .unit_type import Unit_Type
class Product(models.Model):
name = models.CharField(max_length=50)
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)
unit= models.ForeignKey(Unit_Type, on_delete=models.CASCADE, default=1)
Unit_price = models.IntegerField(default=0)
#k_name = models.ForeignKey(UserProfile, on_delete=models.CASCADE)#this is the problem
quantity = models.IntegerField(default=0)
description = models.CharField(max_length=200, default='', null=True, blank=True)
image = models.ImageField(upload_to = 'upload/productsImg/')
#staticmethod
def get_all_products():
return Product.objects.all()
#Filtering by Category Id:
# this method will bring all products by its categoryID
#staticmethod
def get_all_products_by_id(category_id):
if category_id:
return Product.objects.filter(category = category_id)
else:
return Product.get_all_products()
#i am trying to get id from extended user table called UserProfile model and want to get access of #all data from Product model, so that i am trying to written my foreignKey at product table from UserProfile table but it's give me integrity error.
I am trying to give posts category choices , everything works fine but if I add posts from admin panel I get error something like this
Select a valid choice. SSC is not one of the available choices.
this is my Posts/models.py
from django.db import models
from django.core.validators import FileExtensionValidator
# Create your models here.
CATEGORIES = (
('SSC', 'SSCQUESTION'),
('CAT', 'CATQUESTION'),
)
class Category(models.Model):
title = models.CharField(max_length = 120, verbose_name="Title" )
updated_at = models.DateTimeField(auto_now_add=True, verbose_name="Updated at")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
ordering = ['title']
def __str__(self):
return self.title
class Posts(models.Model):
title = models.CharField(max_length=60)
file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
content = models.TextField()
category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE,choices = CATEGORIES)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
# class Meta:
# verbose_name = "Post"
# verbose_name_plural = "Posts"
# ordering = ['-created_at']
def __unicode__(self):
return self.title
def __str__(self):
return self.title
In admin panel this gives error like this
remove choices
category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
Go to the Category table in the admin panel and create some categories there.. Those categories will now be populated in the dropdown in the Post creation page
I'm trying to add User fields into User Profile admin tab to be able to change every User attribute in one tab. The problem is that the cmd returns:
EDIT: Edited code according to Shang Wang's comment but still raises error:
<class 'MyApp.admin.UserProfileUserInline'>: (admin.E202) 'auth.User' has no ForeignKey to 'MyApp.UserProfile'.
In fact, I want to have either User inlined in UserProfile or UserProfile in User. The problem is that UserProfile has field language (note that this is not a Language model) which is through-model and I can't figure out how to inline it into the User (UserProfile can be inlined without problems), so I'm trying to inline User into UserProfile.
Admin.py:
from django.contrib import admin
from models import *
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
admin.site.register(AdminContact)
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'User_Profile'
readonly_fields = ('languages',)
class UserProfileLanguageLevelInline(admin.TabularInline):
model = UserProfileLanguage
class UserAdmin(BaseUserAdmin):
inlines = (UserProfileInline, )
class UserProfileUserInline(admin.StackedInline):
model = User
class UserProfileAdmin(admin.ModelAdmin):
inlines = (UserProfileLanguageLevelInline,User,)
admin.site.unregister(User)
admin.site.register(User,UserAdmin)
admin.site.register(LanguageTuple)
admin.site.register(Language)
admin.site.register(Job)
admin.site.register(UserProfileLanguage)
admin.site.register(Level)
admin.site.register(UserProfile,UserProfileAdmin)
Models.py:
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
class AdminContact(models.Model):
email = models.EmailField()
telephone = models.CharField(max_length=40)
def __unicode__(self):
return self.email
class Language(models.Model):
shortcut = models.CharField(max_length=40)
name = models.CharField(max_length=40)
def __str__(self):
return self.name
class LanguageTuple(models.Model):
language_from = models.ForeignKey(Language, related_name='language_from', null=True)
language_to = models.ForeignKey(Language, related_name='language_to', null=True)
def __str__(self):
return '{} to {}'.format(self.language_from, self.language_to)
class Level(models.Model):
LEVEL_CHOICES = (
('unknown','Unknown'),
('standard','Standard level'),
('professional','Professional level'),
('native','Native speaker level'),
)
name = models.CharField(max_length=40,choices=LEVEL_CHOICES, blank=False, null=False)
price_multiplier = models.FloatField()
def __str__(self):
return self.get_name_display()
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='userprofile')
date_of_birth = models.DateField(null=True,blank=True)
telephone = models.CharField(max_length=40,null=True,blank=True)
IBAN = models.CharField(max_length=40,null=True,blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
MARITAL_STATUS_CHOICES = (
('single', 'Single'),
('married', 'Married'),
('separated', 'Separated'),
('divorced', 'Divorced'),
('widowed', 'Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True, blank=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence', u'It was coincidence'),
('relative_or_friends', 'From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True,
blank=True)
# TRANSLATOR ATTRIBUTES
is_translator = models.BooleanField(default=False)
# language_tuples = models.ManyToManyField(LanguageTuple,blank=True)
languages = models.ManyToManyField(Language, through='UserProfileLanguage')
rating = models.IntegerField(default=0)
number_of_ratings = models.BigIntegerField(default=0)
def __unicode__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
class UserProfileLanguage(models.Model):
userprofile = models.ForeignKey(UserProfile)
language = models.ForeignKey(Language)
level = models.ForeignKey(Level)
class Meta:
unique_together = (('userprofile', 'language'),)
class Job(models.Model):
customer = models.ForeignKey(User, related_name='orders')
translator = models.ForeignKey(User, related_name='jobs',null=True)
price = models.FloatField(null=True,blank=True)
# ZADAVA CUSTOMER
description = models.TextField()
file = models.FileField(null=True,blank=True)
language_tuple = models.ForeignKey(LanguageTuple,related_name='jobs')
specialist = models.BooleanField(blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=False)
is_done = models.BooleanField(default=False)
#property
def has_translator(self):
return self.translator_id is not None
def __str__(self):
return '{}: {}'.format(self.customer,self.language_tuple)
You shouldn't have User model in inlines for UserProfileAdmin, because User is a model not an inline admin. Edit it like this:
class UserProfileAdmin(admin.ModelAdmin):
inlines = (UserProfileLanguageLevelInline, UserProfileUserInline)
I have the following model:
from django.db import models
from django.utils import timezone
class Resource(models.Model):
title = models.CharField(max_length=300)
shortcode = models.CharField(max_length=20, null=True, blank=True)
img = models.URLField(null=True, blank=True)
summary = models.TextField(null=True, blank=True)
url = models.URLField('Link to Resource', null=True, blank=True)
pub_date = models.DateTimeField('date published')
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def __unicode__(self):
return self.title
class Prereq(models.Model):
prereq = models.ForeignKey(Resource, null=True, related_name='prereq_backlink')
resource = models.ForeignKey(Resource, null=True, related_name='prereq_resource')
def __unicode__(self):
return self.prereq.title
class Concurrent(models.Model):
concurrent = models.ForeignKey(Resource, null=True, related_name='concurrent_backlink')
resource = models.ForeignKey(Resource, null=True, related_name='concurrent_resource')
def __unicode__(self):
return self.concurrent.title
class Concomitant(models.Model):
concomitant = models.ForeignKey(Resource, null=True, related_name='concomitant_backlink')
resource = models.ForeignKey(Resource, null=True, related_name='concomitant_resource')
def __unicode__(self):
return self.concomitant.title
I am expecting the autogeneration of an accessor which allows me to get the set of prerequisites of a resource, however neither of these works:
r = Resource.objects.get(id=2)
r.prereq_resource_set # AttributeError: 'Resource' object has no attribute 'prereq_resource_set'
r.prereq_backlink_set # AttributeError: 'Resource' object has no attribute 'prereq_resource_set'
The worst part of all this is that the admin interface works perfectly. I am able to specify prereqs via pulldown and save them and they persist. Here is my admin code:
from django.contrib import admin
from idhhb.models import Resource, Prereq, Concurrent, Concomitant
class PrereqInline(admin.TabularInline):
model = Prereq
fk_name = 'prereq'
extra = 5
class ConcurrentInline(admin.TabularInline):
model = Concurrent
fk_name = 'concurrent'
extra = 3
class ConcomitantInline(admin.TabularInline):
model = Concomitant
fk_name = 'concomitant'
extra = 3
class ResourceAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': 'title shortcode img summary url pub_date'.split() }),
]
inlines = [PrereqInline,]
admin.site.register(Resource, ResourceAdmin)
You shouldn't add the _set suffix for relations which have the related_name attribute:
r = Resource.objects.get(id=2)
r.prereq_resource.all()
r.prereq_backlink.all()