django models CharField - django

I am trying to create a django slideshow app using some existing code and adding some new. I am unsure if what I am doing is correct, I think the problem is in my models.py and as a python beginner I think I need some advice.
models.py
from django.db import models
import datetime
class Slider(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
slideshow = models.ForeignKey('Slideshow')
images = models.ImageField(upload_to='slideshow', max_length=1000, blank=True, null=True)
def __unicode__ (self):
return self.title
class Slideshow(models.model):
name = models.CharField(max_length=50)
touchEnabled = models.BooleanField(blank=True, default=False)
speed = models.IntegerField(blank=True, default=500)
class wrapperClass_options(models.Model):
choices = (('mydiv'))
wrapperClass = models.CharField(blank=True, max_length=20, default=choices)
# div class to wrap the slider in. Change it to prevent using default styles.
pub_date = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.name
I am pretty sure that my BooleanField and IntegerField are ok, but am not so sure about the CharField.
the charfield default is #mydiv but it needs to be able to be changed to whatever a developer needs it to be, am I doing the right thing by creating wrapperclass_options and adding the default to it choices = 'mydiv' or should I be doing something different altogether?
Below is my admin.py
admin.py
from satchmo_slideshow.models import Slider, Slideshow
from django.contrib import admin
class SlideInline(admin.StackedInline):
model = Slider
class SlideshowAdmin(admin.ModelAdmin):
fieldsets = [(title, {'fields': ['name']}),
('speed', {'fields': ['Default: 500ms']}),
('wrapperClass', {'fields': ['Default: mydiv']}),
('touchEnabled', {'fields': ['Default: False']}),
]
inlines = [SlideInline]
list_display = ['name', 'pub_date']
list_filter = ['pub_date']
search_fields = ['name']
admin.site.register(Slideshow, SlideshowAdmin)
using python 2.7 and django 1.4.2

Related

Selecting items from a many to many field to link specific items in the list to a model in the admin panel

I am working on a recipe book app, and I currently have my models connected in this way:
class Tool(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=200)
def __str__(self):
return self.name
class Recipe(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=200)
servings = models.IntegerField(default=1, blank=False)
tools = models.ManyToManyField(Tool)
def __str__(self):
return self.name
The admin panel input currently looks like this:
Upon saving the data as shown in the screenshot, I get the following error:
OperationalError at /admin/recipeBook/recipe/add/
no such table: recipeBook_recipe_tools
Here is my admin.py, just incase it's useful:
from django.contrib import admin
from .models import Recipe, Ingredient, Instruction, Tool
# Register your models here.
class IngredientInline(admin.TabularInline):
model = Ingredient
extra = 2
class RecipeAdmin(admin.ModelAdmin):
fieldsets = [
('Information', {'fields': ['name', 'description', 'servings']}),
('Tools', {'fields': ['tools']})
]
inlines = [IngredientInline]
list_display = ('name', 'description', 'servings')
search_fields = ['name']
list_filter = ['servings']
admin.site.register(Recipe, RecipeAdmin)
admin.site.register(Ingredient)
admin.site.register(Instruction)
admin.site.register(Tool)
If you have an error like this.
Make sure you migrate your database after adding to your models.

Retrieve field values to Django Admin using many to many relationships

I have a simple task: I need to expose player name related to Game in game list (Django Admin). Game object has ManyToMany relationship with Player object via 'players' attribute. The problem is that now I have empty 'players_list' field (empty list means I don't know what to do and just leave it here[enter image description here][1]), though I tried Player.objects.all() and obviously got all players even those who are not bound to particular game.
I feel it has simple solution but my brain refuses to work after 55 opened tabs.
Thanks in advance!
This is my models.py
from django.db import model
class Player(models.Model):
name = models.CharField(max_length=54, default="")
email = models.EmailField(max_length=54)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Game(models.Model):
name = models.CharField(max_length=254, default="")
players = models.ManyToManyField(Player, blank=True, related_name='player_games')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
players_list = []
def __str__(self):
return self.name
and admin.py
from django.contrib import admin
from .models import Game, Player
class PlayerInline(admin.TabularInline):
model = Game.players.through
#admin.register(Player)
class Admin(admin.ModelAdmin):
search_fields = ['name', 'email']
list_display = ('name', 'email', 'created_at', 'updated_at')
inlines = [
PlayerInline,
]
#admin.register(Game)
class AdminAdmin(admin.ModelAdmin):
list_display = ('name', 'created_at', 'updated_at', 'players_list')
inlines = [
PlayerInline,
]
exclude = ('players',)
Pic as it looks now
[1]: https://i.stack.imgur.com/KVJ5y.png
The best approach here will be creating custom method in your model instead of single variable. You will not even have to change your list_display:
class Game(models.Model):
...
def players_list(self):
return self.players.all()
Alternatively, if you want only names of players or anything else from, you can change it (or add another method) to something like that:
class Game(models.Model):
...
def players_list(self):
return [player for player in self.players.all()]
# or
return [player.name for player in self.players.all()]
This is called list comprehension, if you are not familiar with it.

admin panel, show date_created and date_updated?

I tried following an answer at this previous post:
DateTimeField doesn't show in admin system
But maybe I'm just too dim to understand it.
No field of created_at shows up. Could anyone point me in the right direction?
model
class holding_transaction(models.Model):
holdingname = models.ForeignKey(holding, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
admin.py
class holding_transactionAdmin(admin.ModelAdmin):
readonly_fields = ('created_at', )
admin.site.register(holding_transaction, holding_transactionAdmin)
Edit:
Update:
Here is the code that worked for me for an imaginary application called Beatles:
beatles/models.py:
from django.db import models
# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self): # __unicode__ on Python 2
return self.name
beatles/admin.py
from django.contrib import admin
# Register your models here.
from beatles.models import Person
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ('created_at', )
The answer to the question mentioned, states that this is not possible to happen.
Nonetheless, if you want to edit such fields, according to the docs you proceed as follows:
If you want to be able to modify this field, set the following instead
of auto_now_add=True:
For DateField: default=date.today - from datetime.date.today()
For DateTimeField: default=timezone.now - from django.utils.timezone.now()
If you want those fields just to be displayed, you can use the following code:
class YourModelAdmin(admin.ModelAdmin):
readonly_fields = ('created_at', 'updated_at', )
admin.site.register(YourModel, YourModelAdmin)

Showing value (URL/Thumbnail) from Foreign key in Admin

I want to show an small preview image in Django Admin. I have made this hack, which works when the key is in the actual model itself.
class Product(models.Model):
prod_name = models.CharField ("Name", max_length=130)
image = models.URLField(max_length=340, blank=True, null=true)
def admin_image(self):
return '<center><img src="%s"/width="100px"></center>' %(self.image, self.image)
admin_image.allow_tags = True
However, I want it to show an image (read a URL) from a Foreign Key. I tried the following but no luck:
class Product_Option(models.Model):
colour = models.CharField (max_length=80, blank=True, null=True)
size = models.CharField (max_length=80, blank=True, null=True)
image_default = models.URLField(max_length=340, blank=True, null=True) # SHOW this image by
class Product(models.Model):
prod_name = models.CharField ("Name", max_length=130)
image = models.URLField(max_length=340, blank=True, null=true)
Default_Image = models.ForeignKey(Product_Option, blank=True, null= True)
Admin.py
class ProductAdmin(ImportExportModelAdmin):
resource_class = ProductResource
def admin_image(self, obj):
return '<center><img src="%s"/width="100px"></center>' %(obj.Stock_Image.image_default.url, obj.Stock_Image.image_default.url)
admin_image.allow_tags = True
list_display = ('prod_name','admin_image')
readonly_fields = ('admin_image',)
Your code is a little confusing, and you should be careful about putting HTML type code in your models. That being said, assuming you are trying to add thumbnails to your admin via foreignkey relations, this would be the easiest approach:
from django.utils.html import format_html
class ProductAdmin(ImportExportModelAdmin):
resource_class = ProductResource
list_display = ('prod_name', 'admin_image')
readonly_fields = ('admin_image',)
def admin_image(self, obj):
return format_html('<center><img src="{1}"/width="100px"></center>', obj.Default_Image.image_default, obj.Default_Image.image_default)
admin_image.allow_tags = True
Note: Notice the use of format_html(). Always use it in these cases to avoid vulnerabilities, as it escapes possibly malicious code.
Also, you were trying to use image_default.url, which only exists on an ImageField, not a URLField. I removed that as well in favor of just image_default.

Django Admin ManyToManyField

I've made a model (models.py):
class opetest(models.Model):
name = models.CharField(max_length=200)
author = models.ForeignKey(User, related_name='author')
description = models.TextField(u'Test description', help_text = u'Some words about quiz')
pub_date = models.DateTimeField('date published', blank=False)
vacancies = models.ManyToManyField(Vacancy, blank=True)
students = models.ManyToManyField(User, blank=True, related_name='opetests') #This field I want to edit on "User change page"
estimate = models.IntegerField(default = 0, help_text = u'Estimate time in hours. \'0\' - unlimited')
then I try to add inline block to allow assign opetest on 'change user' page (admin.py):
class ProfileAdmin(UserAdmin):
filter_horizontal = ('opetests',)
admin.site.unregister(User)
admin.site.register(User, ProfileAdmin)
And I got an error:
'ProfileAdmin.filter_horizontal' refers to field 'opetests' that is missing from model 'User'.
I want to show opetests like Groups on change user page. How can I achieve that?
Hmm, I don't think you want inlines here.
You want to be using the Django admin's filter_horizontal:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_horizontal
class ProfileAdmin(UserAdmin)
filter_horizontal = ('opetest',)
That will give you the widget that you're describing, used to add/remove Groups on the User Change page.
Ok, based on your edits, updated answer - basically, what we have is a UserProfile, linked to each user.
The UserProfile contains a m2m relationship to opetest - which we show in the admin with a filter_horizontal. End result is something like this:
models.py
from django.db import models
from django.contrib.auth.models import User
class opetest(models.Model):
name = models.CharField(max_length=200)
author = models.ForeignKey(User, related_name='author')
description = models.TextField(u'Test description', help_text = u'Some words about quiz')
pub_date = models.DateTimeField('date published', blank=False)
#vacancies = models.ManyToManyField(Vacancy, blank=True)
students = models.ManyToManyField(User, blank=True, related_name='opetests') #This field I want to edit on "User change page"
estimate = models.IntegerField(default = 0, help_text = u'Estimate time in hours. \'0\' - unlimited')
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
ope = models.ManyToManyField(opetest)
test_flag = models.BooleanField()
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from secondapp.models import UserProfile, opetest
admin.site.unregister(User)
class opetestAdmin(admin.ModelAdmin):
pass
class UserProfileInline(admin.StackedInline):
model = UserProfile
filter_horizontal = ('ope',)
class CustomUserAdmin(UserAdmin):
#filter_horizontal = ('user_permissions', 'groups', 'ope')
save_on_top = True
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'last_login')
inlines = [UserProfileInline]
admin.site.register(User, CustomUserAdmin)
admin.site.register(opetest, opetestAdmin)
Let me know if you have any questions, or need anything further.