Django-photologue ImageModel - django

This is my first project in django and im using photologue for gallery, which is awesome and i really like it.
But there is one thing i dont get, how can i use its ImageModel?
I have a blog-app and with every new blogpost created in the admin interface i woud like to upload a image which is linked to that post.
from django.db import models
from tagging.fields import TagField
from tinymce import models as tinymce_models
from photologue.models import ImageModel
#import datetime
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length=150)
content = tinymce_models.HTMLField()
pub_date = models.DateTimeField(auto_now_add=True)
edit_date = models.DateTimeField(auto_now=True)
tags = TagField()
summary = models.CharField(max_length=30)
thumbnail = ImageModel()
def __unicode__(self):
return self.title
This code above doesn't seem to work or do anything in fact.
I have been rifling through the docs, google ect and trying to understand the photologue source myself but i cant seem to get it to work like i want to.

ImageModel is an abstract class. You can't use it as itself. Instead, you must subclass it:
class BlogImage(ImageModel):
pass
class Blog(models.Model):
...
thumbnail = models.ForeignKey(BlogImage, related_name='blogs')
But, the main purpose of ImageModel is to allow you to create a photo model with additional custom data that still behaves like one of photologue's models. photologue already has Photo which is a real model based on ImageModel that you can use if you just need the defaults.
class Blog(models.Model):
...
thumbnail = models.ForeignKey(Photo, related_name='blogs')

Related

Django - automate CRUD from models (DRY approach)?

I am new to Django but not to developing.
I need to make an application in which user can do CRUD operations (Create, Read, Update, Delete). This functionality should apply to all models and the fields for Create & Update will be auto-generated from model attributes.
What I describe is pretty much the functionality that comes with the Admin page. However, I want to use it in my own app instead of using the Admin app.
For example, let's suppose we have Author and Book models:
(models.py)
from django.db import models
class Author(models.Model):
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
def __str__(self):
return self.last_name
class Book(models.Model):
title = models.CharField(max_length=60)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return self.title
I suppose that the above information (models) could be enough for CRUD operations, without repeating code of the same logic for each model. I am aiming at a functionality like in admin page where all you have to do is register your model.
I am aware of ModelForm and Generic Views but while they help avoiding hard-coding form fields, I have not found a non-repetitive coding approach. I would like to avoid approaches like the following where same code is being duplicated for each model:
(forms.py)
from django import forms
from todo.models import Author, Book
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = '__all__'
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__'
(views.py)
from django.views.generic import CreateView
from.forms import AuthorForm, BookForm
from.models import Author, Book
class AuthorCreateView(CreateView):
model = Author
form_class = AuthorForm
...
class BookCreateView(CreateView):
model = Book
form_class = BookForm
...
So, what is the best approach for a DRY CRUD solution (like in Admin page)? Am I missing any Django features?
Putting my explanation in the comment together, you would get something like this:
from django.views import generic
from myapp.apps import MyAppConfig
from django.forms import modelform_factory
urlpatterns = []
for model in MyAppConfig.get_models():
create_url = path(
f"{model.__class___.__name__.lower()}/create",
generic.CreateView.as_view(
form_class=modelform_factory(model=model, fields='__all__'),
template_name=f"{model._meta.app_label}/create.html",
model=model
),
),
list_url = path(
f"{model.__class__.__name__.lower()}/",
generic.ListView.as_view(
template_name=f"{model._meta.app_label}/list.html",
model=model
),
),
...
urlpatterns.extend([create_url, list_url, read_url, update_url, delete_url])
So the principle is to use the generic view and model form factory, to generate standard crud views, derive path names from model name and use one template per view, in the application (derived from model's app_label).
Using the documentation I linked before, you should be able to piece things together.

How to access the instance from a model manager?

I was told that doesn't make sense as managers operate on all rows not a single instance but I see what I want to achieve done in django-taggit library.
Here: https://github.com/alex/django-taggit/blob/master/taggit/managers.py
And the the installation works as follows:
from django.db import models
from taggit.managers import TaggableManager
class Food(models.Model):
# ... fields here
tags = TaggableManager()
Then to tag anything, one can simply do the following:
apple.tags.add("red", "green", "fruit")
Note: apple not Apple.
Yet, when I try to do it myself, I get: AttributeError: Manager isn't accessible via MyModelName instances!
My code:
from django.db import models
class TagManager(models.Manager):
def add(self, *tags):
print("Testing...")
class List(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=500)
tags = TagManager()
Then I am trying to call the add method as follows:
l = List.objects.create(...)
l.tags.add(...)
How can I make it work?

admin.py: "model = Thing" ,what does this code mean?if without it what gonna happen?

every one,,I am reading a Django practice book,,I saw a code "model = Thing" in admin.py,,,however, when I remove "model = Thing",,,the web program still can run,the admin site looks no difference??,what does this code mean?if without it what gonna happen? my models.py class is Thing
admin.py
from django.contrib import admin
from collection.models import Thing
class ThingAdmin(admin.ModelAdmin):
model = Thing #if I remove this code, the program still can run,,why need this code
list_display = ('name', 'description',)
prepopulated_fields = {'slug': ('name',)}
admin.site.register(Thing, ThingAdmin)
modles.py
from django.db import models
class Thing(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
slug = models.SlugField(unique=True)
Setting a model attribute on the ModelAdmin class will have no effect. You can safely remove that line from your code.
In the Django admin, you specify the model when you call admin.site.register(), or by using the register decorator. This allows you to use the same model admin class for more than one model.
admin.site.register(Thing, ThingAdmin)
admin.site.register(OtherThing, ThingAdmin)
As Jon pointed out in the comments, you do need to specify the model for InlineModelAdmin objects.

Dojo Rich Editor in Django: Correct admin.py Settings?

I'm building a blog, with models "Post" and "Image" like so:
class Post(models.Model):
title = models.CharField(max_length=1000)
author = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
text = models.TextField(max_length=10000)
class Image(models.Model):
post = models.ForeignKey(Post, related_name='images')
image = models.ImageField(upload_to='photos/%Y/%m/%d')
caption = models.CharField(max_length=1000,blank=True)
I've been trying to implement the Dojo rich editor in my admin site by following the example
here:
http://lazutkin.com/blog/2011/mar/13/using-dojo-rich-editor-djangos-admin/
However, there's some kind of interference between settings in my admin.py file that is keeping me from registering both the rich editor and a ModelAdmin class for uploading images associated with an instance of "Post." If I use the following code in my admin.py file:
from django.contrib.admin import site, ModelAdmin
import models
class CommonMedia:
js = (
'https://ajax.googleapis.com/ajax/libs/dojo/1.6.0/dojo/dojo.xd.js',
'editor.js',
)
css = {
'all': ('editor.css',),
}
site.register(models.Post,
Media = CommonMedia,
)
The rich text editor shows up fine. But if I add some code for image uploading fields, like so:
from blogs.models import Post,Image
from django.contrib import admin
from django.contrib.admin import site, ModelAdmin
import models
class CommonMedia:
js = (
'https://ajax.googleapis.com/ajax/libs/dojo/1.6.0/dojo/dojo.xd.js',
'editor.js',
)
css = {
'all': ('editor.css',),
}
class PostImageInline(admin.TabularInline):
model = Image
extra = 5
class PostAdmin(admin.ModelAdmin):
inlines = [PostImageInline]
site.register(models.Post,
list_display = ('text',),
search_fields = ['text',],
Media = CommonMedia,
)
admin.site.unregister(Post)
admin.site.register(Post, PostAdmin)
the rich editor doesn't show up. I'm guessing this is due to the "admin.site.unregister(Post)" line, but if I don't use that I get the error, "The model Post is already registered." If instead I remove both that line and the "Post" from "admin.site.register(Post, PostAdmin)", I get the error: "'MediaDefiningClass' object is not iterable". Does anyone know how to resolve this so I can have both my PostAdmin and rich editor on the same page?
/home/guillaume/mysite/blogs/static/editor.js is incorrect, you should provide an URL here. Probably, /static/editor.js
Also, use web inspector for chrome/safari or firebug for firefox to catch some errors in the console.

Django - "last_modified" or "auto_now_add" for an App (or more than one Model?)

I know Django has a feature of last_modified field (models.DateTimeField(auto_now_add=True)
)..
but let's say I have a certain App, and I want to know when was the last change for any of its Model (I don't really care which model was changed, I just want to know when was the latest change for this app..)
do I really have to write a last_modified field for each model (I have 9 of them for the moment...), and then check for each of them which is the latest?
any help will be appreciated :)
Thanks
You could create a base class that defines the last_modified field...
class YourBaseClassName(models.Model):
last_modified = models.DateTimeField(auto_now=True)
and then inherit from that
class AnotherClass(YourBaseClassName):
another_field = models.CharField(max_length=50)
In The End I made a table for constants for my app (actually I had it before for use of other things).
so the Table looks like this:
from django.db import models
from django.db.models.signals import post_save
class Constant(models.Model):
name = models.CharField(max_length=50)
value = models.CharField(max_length=50)
and added a consant named "version_date".
Than, I added this code to the bottom of my models.py, to track all changes in all the models in the app.
myapp = models.get_app('myapp')
models2track = models.get_models(myapp)
def update_version(sender, **kwargs):
for model in models2track:
post_save.disconnect(update_version, sender=model, dispatch_uid="some_uid"+model._meta.db_table)
version_date = Constant.objects.get_or_create(id=1,name="version date")[0]
version_date.value = str(int(time.time()))
version_date.save()
for model in models2track:
post_save.connect(update_version, sender=model, dispatch_uid="some_uid"+model._meta.db_table)
for model in models2track:
post_save.connect(update_version, sender=model, dispatch_uid="some_uid"+model._meta.db_table)
This way, I don't need to change my DB Schema.. only need to add the code mentioned.
thanks all