If I create a new entry for one particular model it doesn't show up in the django admin.
The Agency Model is causing the trouble.
# catalog.models
class Content(models.Model):
class Meta:
abstract = True
BUNDESLAND_CHOICES = (
('bw', 'Baden-Württemberg'),
('by', 'Bayern'),
('be', 'Berlin'),
('bb', 'Brandenburg'),
('hb', 'Bremen'),
('hh', 'Hamburg'),
('he', 'Hessen'),
('mv', 'Mecklenburg-Vorpommern'),
('ni', 'Niedersachsen'),
('nw', 'Nordrhein-Westfalen'),
('rp', 'Rheinland-Pfalz'),
('sl', 'Saarland'),
('sn', 'Sachsen'),
('st', 'Sachsen-Anhalt'),
('sh', 'Schleswig-Holstein'),
('th', 'Thüringen'),
)
name = models.CharField(max_length=255, verbose_name='Agentur')
address = models.CharField(max_length=255, verbose_name='Straße')
state = models.CharField(max_length=2, choices=BUNDESLAND_CHOICES, verbose_name='Bundesland')
city = models.CharField(max_length=255, verbose_name='Stadt')
zip = models.CharField(max_length=10, verbose_name='PLZ')
phone = models.CharField(max_length=40, blank=True, verbose_name='Telefonnr.')
fax = models.CharField(max_length=40, blank=True, verbose_name='Fax')
email = models.EmailField(verbose_name='E-Mail', help_text='Offizielle E-Mail')
url = models.URLField(verbose_name='URL')
owner = models.CharField(max_length=255, verbose_name='Besitzer')
description = models.TextField(verbose_name='Beschreibung')
category = models.ManyToManyField(Category, verbose_name='Kategorie')
user = models.ForeignKey(User, verbose_name='Benutzer', null=True, blank=True)
slug = models.SlugField(max_length=80, blank=True)
identity = models.CharField(max_length=64, unique=True, blank=True)
identity_used = models.BooleanField(default=False)
show = models.BooleanField(default=False, verbose_name='Anzeigen')
tp = models.DateTimeField(auto_now_add=True)
# agency.models
class AgencyActiveManager(models.Manager):
def get_query_set(self):
return super(AgencyActiveManager,self).get_query_set().filter(show=True)
class Agency(Content):
clients = models.TextField(verbose_name='Klienten')
active = AgencyActiveManager()
objects = models.Manager()
def __unicode__(self):
return self.name
def save(self, **kwargs):
if not self.identity:
self.identity = hashlib.sha256('%s:%s' %(get_word(),datetime.datetime.now())).hexdigest()
if not self.slug:
self.slug = slugify(self.name, instance=self)
super(Agency, self).save(**kwargs)
# agency.admin
from django.contrib import admin
from agency.models import Agency
admin.site.register(Agency)
I created a new Agency entry in the admin and saved it.
Querying via the python shell shows that the save worked
In [15]: Agency.objects.all()
Out[15]: [<Agency: Argentur>]
The admin page says:
'0 agencys'
If I try manually calling the url /admin/agency/agency/1/ I get a 404 saying that there is no agency object with a primarykey 1
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/admin/agency/agency/1/
Das agency-Objekt mit dem Primärschlüssel u'1' ist nicht vorhanden.
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
But pythons shell says:
In [16]: Agency.objects.all()[0].pk
Out[16]: 1
Am I missing something extremely obvious?
My guess would be that it has something todo with the abstract model but I can't figure out what.
The first manager listed in the model class definition is the one that is used for the admin site and a number of other operations.
There have been a number of bugs in Django related to using a manager that does not return all instances as the default manager. IMHO, you are best to use a standard manager as the default, and add any more restrictive ones afterwards.
In fact, I no longer write models that use more than one manager. I would write
class AgencyManger(models.Manager):
def active(self):
return self.filter(show=True)
and use this as Agency.objects, so a root QuerySet for active objects is Agency.objects.active() rather than Agency.active.all(). This means .objects. will always have the same well-known behaviour. It's also easier to spot and understand in code.
Related
I have a function in my models.py that adds the news I pass to it via a URL using OpenGraph. This process works fine, but there are some websites that give me an error, how can I use a try except to control this error and the application does not crash?
When the error occurs, I would like the application in the admin panel to return me to the same place where it was before, but indicating the error.
Best regards and thank you very much!
My models.py:
class Post(models.Model):
title = models.CharField(max_length=200, verbose_name="Título", null=True, blank=True)
content = RichTextField(verbose_name="Contenido", null=True, blank=True)
published = models.DateTimeField(verbose_name="Fecha de publicación", default=now, null=True, blank=True)
image = models.ImageField(verbose_name="Imagen", upload_to="blog", null=True, blank=True)
author = models.ForeignKey(UserManegement, verbose_name="Autor", on_delete=models.CASCADE)
categories = models.ManyToManyField(Category, verbose_name="Categorias", related_name="get_posts")
url_web = models.URLField(verbose_name="URL", null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, verbose_name='Fecha de creacion')
updated = models.DateTimeField(auto_now=True, verbose_name='Fecha de ediccion')
class Meta:
verbose_name = "entrada"
verbose_name_plural = "entradas"
ordering = ['-created']
def __str__(self):
return self.title
The function in which I want to insert the try except. It is in the same models.py:
#receiver(pre_save, sender=Post)
def url_processor(sender, instance, *args, **kwargs):
if instance.url_web:
title, description, image = web_preview(instance.url_web)
instance.title = title
instance.content = description
path = 'blog/' + uuid.uuid4().hex + '.png'
instance.image = path
img_data = requests.get(image).content
with open('media/' + path, 'wb') as handler:
handler.write(img_data)
else:
return
This is the error when entering this url: Web error
requests.exceptions.MissingSchema: Invalid URL 'None': No schema supplied. Perhaps you meant http://None?
The error from what I have been seeing, is due to the 21 of the URL, which the Python request library in version 3.6.10 takes it as an error. It only happens with URLs that have some number in their domain.
Instead of signals use this code in model clean method.
from django.core.exceptions import ValidationError
Class YourModel(models.Model):
# fields
def clean(self, *args, **kwargs):
try:
# your signal code here
except:
raise ValidationError('Your message')
I'm having trouble finding the best way to override and add custom html to an edit/add model form in my Django admin site.
Here are the two models involved here:
Icon model used to store "Font Awesome" Icons:
class Icon(models.Model):
name = models.CharField(max_length=100, null=False)
style = models.CharField(max_length=10, choices=STYLE_CHOICES, null=False)
retired = models.BooleanField(default=False)
def delete(self):
self.retired = True
self.save()
objects = NotRetiredManager()
objects_deleted = DeletedManager()
def __str__(self):
return self.name
Workbook model that holds foreign key reference to the above Icon model:
class Workbook(models.Model):
client = models.ForeignKey(Client, on_delete=models.SET_NULL, null=True)
icon = models.ForeignKey(Icon, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=100)
workbookLink = models.CharField(max_length=1000)
retired = models.BooleanField(default=False)
def delete(self):
self.retired = True
self.save()
objects = NotRetiredManager()
objects_deleted = DeletedManager()
def __str__(self):
return self.name
Here are the overridden admin models for the above models:
class BaseAdmin(AdminImageMixin, admin.ModelAdmin):
def delete_queryset(self, request, queryset):
for obj in queryset:
obj.delete()
#admin.register(Workbook)
class WorkbookAdmin(BaseAdmin):
list_display = ("name", "client")
list_filter = (NameFilter, ClientNameFilter)
ordering = ("name", )
#admin.register(Icon)
class IconAdmin(BaseAdmin):
fields = ("name", "style", "icon_display")
list_display = ("icon_display", "name", "style" )
list_display_links = ("icon_display", "name")
list_filter = (NameFilter, )
ordering = ("name", )
def icon_display(self, obj):
return mark_safe(f'<i class="{obj.style}{obj.name}"></i>')
readonly_fields = ["icon_display"]
Here is a list display of some Icons I have in my database:
Currently, the add/edit page for a Workbook on my Admin Site looks like this:
I would like for that dropdown in that second screenshot to be customized similar to the "Icon Display" column in that first screenshot so that a user would choose from graphical list of icons as opposed to the default choicefield form containing the Icon names.
I've looked into the Django docs as well as similar questions on here such as this Similar Stack Overflow Question; however, I'm not fully understanding the proper way to implement something like this.
I hope the information I provided about my app is useful. Please let me know if you'd like me to provide any additional information, or add any clarifications!
I am using CreateView from DJango to save data to the DB. To do this, I am following the instructions here: Form handling with class-based views
According to my understanding, after the data is saved to the DB, the control is to be passed to a type of "success screen" - in this case, for my scenario, control is to be passed to a "details page". The details page is represented by the following URL:
url(r'^owner/(?P<pk>[0-9]+)/contact/details/$', views.MstrstoreheadcontactDetailsView.as_view(),
name='owner-contact-details'),
Below (in the class Mstrstoreheadcontact) the "details page" is being called by the get_absolute_url function (which is part of the Mstrstoreheadcontact model)
from the models.py file
class Mstrstoreheadcontact(models.Model):
tenantid = models.ForeignKey('Mstrauthowner', models.DO_NOTHING, db_column='tenantid', blank=True, null=True)
contactid = models.BigIntegerField(primary_key=True, default=0)
genderid = models.BigIntegerField(blank=True, null=True, default=0)
firstname = models.CharField(max_length=20, blank=True, null=True)
lastname = models.CharField(max_length=20, blank=True, null=True)
officephoneno = models.CharField(max_length=20, blank=True, null=True)
cellphoneno = models.CharField(max_length=20, blank=True, null=True)
class Meta:
managed = False
db_table = 'MstrStoreHeadContact'
def get_absolute_url(self):
return reverse('masterdata:owner-contact-details', kwargs={'pk': self.contactid})
For me the code: return reverse('masterdata:owner-contact-details', kwargs={'pk': self.contactid} is supposed to take the control to the "details page" that will display the new record that has been added to the DB.
The problem
When the code above is executed, the variable self.contactid is set to 0. See below:
This results in the following URL to be placed in the address bar:
http://127.0.0.1:8000/masterdata/owner/0/contact/details
Because of the "0", this leads to a 404 error. In the DB, the value is set - for example to 10.
Again, the data saves to the DB JUST FINE- there is no problem with
this part. The problem lies with what happens AFTER the data is saved
to the DB.
Below are some entries from the urls.py file
from the urls.py file
url(r'^owner/(?P<pk>[0-9]+)/contact/details/$', views.MstrstoreheadcontactDetailsView.as_view(),
name='owner-contact-details'),
url(r'^owner/(?P<tenantid>[0-9]+)/contacts/add/$', views.MstrstoreheadcontactCreateView.as_view(),
name='owner-contact-add'),
from the views.py file
class MstrstoreheadcontactCreateView( CreateView ):
model = Mstrstoreheadcontact
fields = [ 'firstname', 'lastname', 'genderid', 'officephoneno', 'cellphoneno']
def form_valid(self, form):
contact = form.save(commit=False)
contact.tenantid = Mstrauthowner.objects.get(tenantid=self.kwargs['tenantid'])
return super(MstrstoreheadcontactCreateView, self).form_valid(form)
It seems like the code is not getting the data back from the DB properly (after the data has been saved). What can I do to fix the problem?
TIA
Well, thank goodness for debuggers. The following changes resolved all the problems for me :-)
views.py
class MstrstoreheadcontactCreateView( CreateView ):
model = Mstrstoreheadcontact
fields = [ 'firstname', 'lastname', 'genderid', 'officephoneno', 'cellphoneno']
def form_valid(self, form):
form.instance.tenantid = Mstrauthowner.objects.get(tenantid=self.kwargs['tenantid'])
return super(MstrstoreheadcontactCreateView, self).form_valid(form)
models.py
class Mstrstoreheadcontact(models.Model):
tenantid = models.ForeignKey('Mstrauthowner', models.DO_NOTHING, db_column='tenantid', blank=True, null=True)
contactid = models.BigIntegerField(primary_key=True, default=0)
[... snip ..]
def get_absolute_url(self):
[... snip ...]
return reverse('masterdata:owner-contact-details', kwargs={'pk': self.tenantid.pk})
I'm building an API using Tastypie with Django and I've run into a bit of an issue.
I have a model called a Moment (basically a blog post, with a title and body text), and I want to be able to attach comments to it and retrieve them via the API. I'm using django.contrib.comments with Django 1.6.5 and Tastypie 0.11.1.
Now, according to the Tastypie documentation, this should be straightforward. What I've implemented is pretty close to that. This is my models.py:
class Moment(models.Model):
"""
Represents a Moment - a statement by a user on a subject
"""
ZONE_CHOICES = (
('Communication', 'Communication'),
('Direction', 'Direction'),
('Empathy', 'Empathy'),
('Flexibility', 'Flexibility'),
('Motivation', 'Motivation'),
('Ownership', 'Ownership'),
('Persistence', 'Persistence'),
('Reliability', 'Reliability'),
('Teamwork', 'Teamwork'),
)
STATUS_CHOICES = (
('Open', 'Open'),
('More Info', 'More Info'),
('Closed', 'Closed'),
)
title = models.CharField(max_length=200)
text = models.TextField()
datetime = models.DateTimeField(default=timezone.now())
zone = models.CharField(max_length=200,
choices=ZONE_CHOICES)
sender = models.ForeignKey(Student, blank=True, null=True, related_name="sender")
status = models.CharField(max_length=200,
default='Open',
choices=STATUS_CHOICES)
recipient = models.ForeignKey(Sponsor, blank=True, null=True, related_name="recipient")
comments = generic.GenericRelation(Comment, object_id_field='object_pk')
def save(self, *args, **kwargs):
"""
Override the save() method to set the recipient dynamically
"""
if not self.recipient:
self.recipient = self.sender.sponsor
super(Moment, self).save(*args, **kwargs)
def __unicode__(self):
return self.title
class Meta:
ordering = ["-datetime"]
And this is my api.py:
class MomentResource(BaseResource):
"""
Moment resource
"""
sender = fields.ForeignKey(StudentResource, 'sender', full=True, readonly=True)
comments = fields.ToManyField('myapp.api.CommentResource', 'comments', blank=True, null=True)
class Meta:
"""
Metadata for class
"""
queryset = Moment.objects.all()
resource_name = 'moment'
always_return_data = True
authentication = BasicAuthentication()
authorization = DjangoAuthorization()
filtering = {
'zone': ALL,
}
class CommentResource(ModelResource):
"""
Comment resource
"""
moment = fields.ToOneField(MomentResource, 'moment')
class Meta:
queryset = Comment.objects.all()
resource_name = 'comments'
However, the comments always come back blank.
Now, I know that the model seems to be correct because in the Django shell, the following returns the comments on a Moment:
Moment.objects.all()[0].comments.all()
I think the problem is therefore in api.py, but I haven't been able to track it down. Can anyone see where I've gone astray?
Finally got it working with the following:
class MomentResource(BaseResource):
"""
Moment resource
"""
sender = fields.ForeignKey(StudentResource, 'sender', full=True, readonly=True)
comments = fields.ToManyField('myapp.api.CommentResource', 'comments', null=True, full=True)
class Meta:
"""
Metadata for class
"""
queryset = Moment.objects.all()
resource_name = 'moment'
always_return_data = True
authentication = BasicAuthentication()
authorization = DjangoAuthorization()
filtering = {
'zone': ALL,
}
class CommentResource(BaseResource):
"""
Comment resource
"""
moment = fields.ToOneField(MomentResource, 'content_object')
class Meta:
queryset = Comment.objects.all()
resource_name = 'comments'
I'm pretty sure the issue was with returning the Moment object from CommentResource, which was resolved by changing the attribute to content_object.
So at work we are using django-publish for publishing case studies. Whenever a case study is published, it is viewable by a regular user. However if it is in draft mode, and user is logged in as an admin, on the index page he should be able to see all the case studies, whether published or still in draft mode, that would link to the actual case study pages for each, however for studies in draft mode '?draft' should be appended to the individual url. Hopefully that makes sense.
My problem is that 'is_public' field, inherited from the Publishable class, shows up correctly when viewed by the regular user, however when admin is logged in and is trying to view the page, is_public field always shows up as False, even though it is clearly True in the database.
def get_absolute_url(self):
if self.slug:
if self.is_public:
return reverse('case-study', args=(self.slug,))
else:
return reverse('case-study', args=(self.slug,)) + '?draft'
return reverse('work',)
I have this from the model get_absolute_url method, thus when logged in as admin, every case study has '?draft' appended to it.
I would appreciate any help with this.
This is the full model:
class CaseStudy(Publishable, Sortable):
# Text
title = models.CharField(max_length=100)
subtitle = models.CharField(max_length=100, blank=True, null=True)
description = models.CharField('Summary', max_length=255)
challenge = models.TextField('The Challenge')
solution = models.TextField('Our Solution')
# Images
image = models.ImageField('Thumbnail', upload_to="case-study/thumbs")
header = models.ImageField('Header Image', upload_to="case-study/header")
# Client Meta
client = models.ForeignKey(Client, null=True, blank=True)
expertise = models.ManyToManyField(Expertise)
capability = models.ManyToManyField(Capabilty)
services = models.TextField(blank=True, help_text='One per line')
# Formatting
scheme = models.CharField('Color Palette', max_length=100, choices=COLOR_SCHEMES)
# Display Options
home_page = models.BooleanField('Feature on Home Page?', default=False)
work_page = models.BooleanField('Feature on Work Page?', default=False)
# Meta
slug = models.SlugField()
created = CreationDateTimeField()
modified = ModificationDateTimeField()
class Meta(Publishable.Meta, Sortable.Meta):
verbose_name = 'Case Study/Story'
verbose_name_plural = 'Case Studies'
class PublishMeta(Publishable.PublishMeta):
publish_reverse_fields = ['sections', 'related_projects']
def __unicode__(self):
return u'%s' % self.title
def get_absolute_url(self):
if self.slug:
if self.is_public:
return reverse('case-study', args=(self.slug,))
else:
return reverse('case-study', args=(self.slug,)) + '?draft'
return reverse('work',)