how to display a pdf in django admin? instead of the link - django

models.py
class Equipo(models.Model):
CODIGO = models.CharField(primary_key=True, max_length=5 )
DESCRIPCION = models.CharField(max_length=50, default='')
TITULO = models.FileField(upload_to = "Archivos/Titulos/", default='', blank=True)
admin.py
from django.contrib import admin
from .models import Equipo
class EquipoAdmin(admin.ModelAdmin):
list_display = ('CODIGO', 'DESCRIPCION', 'TITULO')
admin.site.register(Equipo, EquipoAdmin)
I need to see something like this

You can use below code result
# admin.py
list_display = ('title', 'description', 'embed_pdf', 'deadline')
def embed_pdf(self, obj):
try:
html = f'<iframe src="{obj.add_file.url}" width="200px" height="200px" frameborder="2"></iframe>'
formatted_html = format_html(html.format(url=obj.add_file.url))
return formatted_html
except Exception as e:
pass
embed_pdf.short_description = "File/Image"
admin.site.register(Order, OrderAdmin)

Related

Add User full_name in list_filter admin site

I can't figure out how to add the User full_name in the list_filter.
My Blog model is as follows:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
class User(AbstractUser):
pass
class Post(models.Model):
POST_STATUS = (('borrador', 'Borrador'), ('publicado', 'Publicado'))
title = models.CharField('titulo', max_length=100)
body = models.TextField('cuerpo')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts', verbose_name='autor')
created = models.DateTimeField('creado', auto_now_add=True)
published = models.DateTimeField('publicado', auto_now=True)
updated = models.DateTimeField('actualizado', auto_now=True)
slug = models.SlugField(max_length=100, unique_for_date='published')
status = models.CharField(max_length=10, choices=POST_STATUS, default='borrador')
class Meta:
ordering = ('-published',)
def __str__(self):
return self.title
As you can see, I have created a custom user model just in case I have to change it in the future.
In the Blog model, there is a 'author' field which uses the User as FK.
I want to add the posibility to filter by 'author' in the Blog's admin site. To do this I tried the following:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User, Post
admin.site.register(User, UserAdmin)
#admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'status', 'published')
list_filter = ('author' , 'status', 'published')
search_fields = [('title',), ('body',)]
prepopulated_fields = {'slug': ('title',)}
raw_id_fields = ('author',) # Reemplaza el drop-down para que parezca una lupa (para FKs)
date_hierarchy = 'published'
ordering = ('status', 'published')
The problem is that the filter by 'author' doesn't appear in the admin site:
If I do this: list_filter = ('author__last_name' , 'status', 'published') the filter shows up, but it looks like this ('appellido' means last_name in Spanish:
I would like the filter's text to be 'por autor (by author)' and be able to filter by the author's full name.
Is that possible?
Thanks in advance!!
Probably you can do that with django.contrib.admin.SimpleListFilter:
from datetime import date
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
class PerAuthorListFilter(admin.SimpleListFilter):
title = _('Per Author')
parameter_name = 'per_author'
def lookups(self, request, model_admin):
authors = []
for u in User.objects.all():
authors.append((u.pk, '{} {}'.format(u.first_name, u.last_name)))
return authors
def queryset(self, request, queryset):
queryset = super().queryset(request, queryset)
return queryset.filter(author=self.value())
#admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_filter = [PerAuthorListFilter, ...]

Django multi language model / filter post by languages

There is my simple blog model;
class Article(models.Model):
author = models.ForeignKey("auth.User",on_delete = models.CASCADE, verbose_name="Author")
title_en = models.CharField(max_length = 120, verbose_name="Title_En")
title_de = models.CharField(max_length = 120, verbose_name="Title_De")
category = models.ForeignKey('Category', on_delete = models.CASCADE, null=True, blank=True)
content_en = RichTextField(verbose_name="Content_En")
content_de = RichTextField(verbose_name="Content_De")
created_date = models.DateTimeField(auto_now_add=True, verbose_name="Created Date")
image = models.ImageField(blank=True, null=True, verbose_name="Add Photo (.jpg .png)")
slug = models.SlugField(unique=True, max_length = 130)
def __str__(self):
return self.title
I use url's with language like this;
domainname.com/en/
domainname.com/de/
For example, how can I show only the contents that belong to title_de and content_de in the domainname.com/de urls?
How can I do filtering with language? Is there an easy solution to this?
(I usage django 2.1.2. i try django-modeltranslation or others dont work this django version...)
Thanks...
You can create a descriptor class that wraps the translated fields e.g.,
from django.utils import translation
class TranslatedField:
def __init__(self, field_name):
self.partial_field_name = field_name
def __get__(self, obj, objtype):
return getattr(obj, self.field_name)
def __set__(self, obj, value):
return setattr(obj, self.field_name, value)
#property
def field_name(self):
language_code = translation.get_language()
rerurn self.partial_field_name + '_' + language_code
class Article(models.Model):
title_en = models.CharField(max_length=120)
title_de = models.CharField(max_length=120)
title = Translated Field('title')
Then you can do
article = Article.objects.create(
title_en='In english',
title_de='In German'
)
print(article.title) # 'In english'
translation.set_language('de')
print(article.title) # 'In German'
article.title = 'In German!'
print(article.title) # 'In German!'
translation.set_language('en')
print(article.title) # 'In english'
(Untested, so there may be typos)
I would use something out of the box like https://github.com/deschler/django-modeltranslation
Filtering based on keyward argument is one of the option for this problem.I would prefer to add a language field 'EN' or 'DE' rather than repeating same kind of title and content field and filtering based on that. For example,
Article Model can be like
class Article(models.Model):
LANGUAGE_TYPES = (
('EN', 'EN'),
('DE', 'DE'),
)
author = models.ForeignKey("auth.User",on_delete = models.CASCADE, verbose_name="Author")
title = models.CharField(max_length = 120, verbose_name="Title")
category = models.ForeignKey('Category', on_delete = models.CASCADE, null=True, blank=True)
content = RichTextField(verbose_name="Content")
created_date = models.DateTimeField(auto_now_add=True, verbose_name="Created Date")
image = models.ImageField(blank=True, null=True, verbose_name="Add Photo (.jpg .png)")
slug = models.SlugField(unique=True, max_length = 130)
language = models.CharField(
max_length=10, choices=LANGUAGE_TYPES)
def __str__(self):
return self.title
Our urls can be like
from django.urls import path
from .views import (ArticleView)
urlpatterns = [
path('article/<slug:type>/', ArticleView.as_view(), name='article'),
]
And Our view can be like
from rest_framework import views, status
from .serializers import ArticleSerializer
from .models import Article
class ArticleView(views.APIView):
def get(self, request):
article_language_type = self.kwargs.get('type', None)
articles = Article.objects.filter(language=article_language_type)
serializer = ArticleSerializer(articles, many=True)
if serializer.is_valid():
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Nested router not working

I'm new to Django and am struggling to get nested routers working. Basically, I'm trying to model the endpoint /api/v1/organizers/1/events/1, where I have Event and Organizer models as follows:
class Event(models.Model):
class Meta:
db_table = 'events'
STATUS_CHOICES = (
('scheduled', 'Scheduled'),
('completed', 'Completed'),
('cancelled', 'Cancelled')
)
name = models.TextField()
purpose = models.TextField()
date_time = models.DateTimeField()
description = models.TextField()
programme = models.TextField()
entry_fee = models.DecimalField(max_digits=6, decimal_places=2)
status = models.TextField(choices=STATUS_CHOICES)
comments = models.TextField(null=True)
people_invited = models.ManyToManyField('Contact', through='EventInvitation')
organizer = models.ForeignKey('Organizer', on_delete=models.CASCADE)
class Organizer(models.Model):
STATUS_CHOICES = (
('inactive', 'Inactive'),
('active', 'Active'),
)
class Meta:
db_table = 'organizers'
first_name = models.TextField()
middle_name = models.TextField(null=True)
last_name = models.TextField(null=True)
email = models.OneToOneField('Email', on_delete=models.CASCADE)
company_name = models.TextField(null=True)
company_description = models.TextField(null=True)
password = models.TextField()
login_token = models.TextField(null=True)
registered_on = models.DateTimeField(null=True)
status = models.TextField(choices = STATUS_CHOICES, default='inactive')
I created another app called rest_api to handle the API. The models are stored in an app called shared_stuff. Anyway, here's the project-level urls.py (don't mind the front_end app for now):
from django.conf.urls import include, url
urlpatterns = [
url(r'^api/v1/', include('rest_api.urls')),
url(r'^', include('frontend.urls')),
]
And here's the urls.py from the app rest_api:
from django.conf.urls import url, include
from rest_framework_nested import routers
from .views import *
router = routers.SimpleRouter()
# /organizers/12/events/1
router.register(r'organizers', OrganizerViewSet, base_name='organizers')
organizer_router = routers.NestedSimpleRouter(router, r'organizers', lookup='organizers')
organizer_router.register(r'events', EventViewSet, base_name='organizers-events')
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^', include(organizer_router.urls)),
]
Here's the serializers.py for rest_api app:
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = ['id', 'name', 'purpose', 'date_time', 'description', 'programme', 'entry_fee', 'status', 'comments']
class OrganizerSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Organizer
fields = ['id', 'first_name', 'middle_name', 'last_name', 'email', 'company_name', 'company_description', 'registered_on', 'status']
events = serializers.HyperlinkedIdentityField(
view_name = 'events_list',
lookup_url_kwarg = 'organizer_pk'
)
And finally, here's the views.py from the app rest_api:
from rest_framework import viewsets
from .models import *
from .serializers import *
class EventViewSet(viewsets.ModelViewSet):
def list(self, request, organizer_pk=None, name='events_list'):
events = self.queryset.filter(organizer=organizer_pk)
serializer = EventSerializer(events, many=True)
return Response(serializer.data)
class OrganizerViewSet(viewsets.ModelViewSet):
def list(self, request, name='organizers_list'):
data = Organizer.objects.all()
serializer = OrganizerSerializer(data, many=True)
return Response(serializer.data)
I'm sure there are many things broken in my code, and that's where I need help. The problem is I'm getting the following error:
TypeError: list() got an unexpected keyword argument 'organizers_pk'
I'm not sure what's wrong, and will appreciate some help!
I got it working by changing the EventViewSet to the following:
def list(self, request, organizers_pk=None, name='events_list'):
events = self.queryset.filter(organizer=organizers_pk)
serializer = EventSerializer(events, many=True)
return Response(serializer.data)
I'm not sure why, but the expected keyword argument name is organizers_pk, whereas I had organizer_pk. I would like to know why this is so, but other than that my problem is solved for now.

list_display of the model with foreign key

I have the following django model.
In the django admin model of TestCase table, in its list_display, i want to display the most recent comment and the modifier name of Remark table.
models.py
from django.db import models
class Release(models.Model):
title = models.CharField(max_length=128)
start_time = models.DateField('Release Start Date')
release_date = models.DateField('Release Ended Date')
def __str__(self):
return self.title
class TestCase(models.Model):
query = models.CharField(max_length=256)
ksq_id = models.IntegerField()
status = models.CharField(max_length=64)
release = models.ForeignKey(Release) # Release can have many test cases
def __str__(self):
return self.query
class Remark(models.Model):
owner = models.CharField(max_length=64)
module = models.CharField(max_length=64)
comment = models.CharField(max_length=1024)
modified_ts = models.DateTimeField('date modified', auto_now=True)
modifier = models.CharField(max_length=64)
testcase = models.ForeignKey(TestCase) # Testcase can have many Re
admin.py
from django.contrib import admin
from kramer_release.models import Release, TestCase, Remark
class RemarksInline(admin.TabularInline):
model = Remark
extra = 0
class RemarkAdmin(admin.ModelAdmin):
list_display = ('owner', 'module', 'testcase_query')
def testcase_query(self, obj):
return obj.testcase.query
class TestCaseAdmin(admin.ModelAdmin):
inlines = [RemarksInline]
list_display = ('query', 'status')
admin.site.register(Release)
admin.site.register(TestCase, TestCaseAdmin)
admin.site.register(Remark, RemarkAdmin)
You can defined a function to get the latest comment as part of you admin class, something like:
class TestCaseAdmin(admin.ModelAdmin):
inlines = [RemarksInline]
list_display = ('query', 'status', 'latest_comment')
def latest_comment(self, obj):
remarks = Remark.objects.filter(testcase=obj).order_by('-modified_ts')
if remarks:
return '%s - %s' % (remarks[0].comment, remarks[0].modifier)
return None
see the docs

Django admin returns TypeError

I am not able to login into admin panel in django app.
It returns error (listing here: http://dpaste.com/1437248/ ).
my admin.py:
from app.models import *
from django.contrib import admin
admin.site.register(Product, Product.Admin)
my models.py (partially):
class Product(BaseModel):
company = models.ForeignKey(Company, null=True, blank=True)
title = models.CharField(max_length=128)
description = models.TextField()
category = models.ForeignKey(ProductCategory, null=True, blank=True)
price = models.DecimalField(max_digits=5,decimal_places=2)
image = models.ImageField(upload_to=product_upload_to)
thumb = models.ImageField(upload_to=thumb_upload_to)
def save(self, force_update=False, force_insert=False, thumb_size=(120,120)):
image = Image.open(self.image)
image.thumbnail(thumb_size, Image.ANTIALIAS)
temp_handle = StringIO()
image.save(temp_handle, 'png')
temp_handle.seek(0) # rewind the file
suf = SimpleUploadedFile(os.path.split(self.image.name)[-1],
temp_handle.read(),
content_type='image/png')
self.thumb.save(suf.name+'.png', suf, save=False)
super(Product, self).save(force_update, force_insert)
class Admin(admin.ModelAdmin):
list_display = ('title','price')
EDIT:
Now I am sure that this error isn't caused by admin.py/Admin class - I deleted content of admin.py and error is still present.
The model admin class shouldn't be inside your Product model. Define it in admin.py.
from app.models import *
from django.contrib import admin
class ProductAdmin(admin.ModelAdmin):
list_display = ('title','price')
admin.site.register(Product, ProductAdmin)