Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Creación del modelo de posts

18/37
Recursos

Para reflejar los cambios en la base de datos, siempre que se crea o se edita un modelo debemos cancelar el server, ejecutar makemigrations, migrate y luego de nuevo volver a correr el servidor con runserver.
Con respecto a las imágenes, Django por defecto no está hecho para servir la media, pero editando las urls logramos que se puedan mostrar. Para servir archivos de media, usamos MEDIA_ROOT y MEDIA_URLS.

Reto de la clase:
Crea el modelo de posts y regístralo en el admin.

Aportes 69

Preguntas 19

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Registrando a Post en el admin

from django.contrib import admin
from posts.models import Post
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """Posts Admin model"""

    list_display = ('pk', 'user', 'photo')
    list_display_links = ('pk', 'user')
    list_editable = ('photo',)
    list_filter = (
                'created',
                'modified'
    )

Les dejo está información por si a alguno le sirve. Estoy utilizando Django 3.1.1, pueden indicar el path de los archivos media de la siguiente manera:

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

Asi me quedo el PostAdmin.

"""Posts admin classes"""
#Django
from django.contrib import admin

#Models
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
  list_display = ('pk', 'user', 'title','photo',)
  list_display_links = ('pk', 'user',)
  list_editable = ('title', 'photo',)
  search_fields = ('user__username','title',)
  readonly_fields = ('created', 'modified')

Y así el sitio de admin de Django

Si tienen problemas al tratar de crear una tabla pero NO se les crea por alguna razón haciendo las migraciones… alli está la solución

Reto

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display=('pk', 'title', 'created', 'modified')
    list_display_links=('pk', 'created')
    list_editable= ('title',)
    search_fields = (
        'created',
        'modified'
    )
    list_filter = (
        'title',
        'created'
    )

    #Evitar que ciertos campos sean editables
    readonly_fields = ('created', 'modified')

😃 Me paso que use

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Lo que me causo error, pues al parecer estaba esperando un objeto y no una tupla.
De forma que no avanzaba… luego de un par de revisiones encontré (no en la documentación) que una forma de solucionar era:

MEDIA_ROOT = (BASE_DIR / 'media')

Espero les sea útil.

Muy interesante pero creo que no es necesario referenciar en el modelo a user y profile, solo con profile se podria llegar a los datos del usuario por la relación que existe entre esos dos modelos, muchas gracias muy bueno el curso!!

La forma en como se configura el MEDIA_ROOT que se aprecia en esta clase esta desactualizado y les arrojara error

os.path.join(BASE_DIR, 'media')

La forma actualizada es más simple

BASE_DIR / 'media'

Creo que es importante remarcar que es más fácil hacer el .format de esta manera y queda más legible

    def __str__(self):
        #return title and username
        return f'{self.title} by @{self.username}

Si les sale este error 😄

platzigram/platzigram/settings.py", line 127, in <module>
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
NameError: name 'os' is not defined

solo coloquen

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

Buen truco👌, prácticamente todo esta en la documentación. 💙

También se podría agregar lo siguiente para cuando Django está en modo debug:

if settings.DEBUG:
    urlpatterns = urlpatterns + \
        static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Mi PostAdmin

# Django
from django.contrib import admin
# Models
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('pk', 'user', 'profile', 'title', 'photo')
    list_display_links = ('pk', 'user')

search_fields = ('user__username', 'title',)
    list_filter = (
        'created',
        'modified',
        'user__is_active',
        'user__is_staff'
        )
readonly_fields = ('created', 'modified', 'user')

fieldsets = (
        ('Post', {
            'fields': (('title', 'photo'),)
        }),

        ('Metadata', {
            'fields': (
                ('user',),
                ('created', 'modified'),
            )
        })
    )

Anexo mi reto

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from posts.models import Post


class PostAdmin(admin.ModelAdmin): 

    list_display = ('pk', 'user', 'profile', 'photo')
    list_display = ('pk', 'user')
    list_editable = ('title', 'photo')
    search_fields = ('post__user', 'post__profile')
    list_filter = ('crated', 'modified')

    readonly_fields = ('created', 'modified',)```

Para nuevas versiones de Django funciona configurar en el setting de platzigram la media de la siguiente forma:

MEDIA_ROOT = BASE_DIR / 'media’
MEDIA_URL = ‘media/’

Agregando Posts al Admin:

#Importaciones de Django
from django.contrib import admin

#Importaciones locales
from posts.models import Posts

# Register your models here.
@admin.register(Posts)
class PostAdmin(admin.ModelAdmin):
    pass

Reto

from django.contrib import admin
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):

    list_display = ('pk', 'user', 'title', 'photo')
    list_display_links = ('pk', 'user')
    list_editable = ('title', 'photo')

    search_fields = ('pk','title')

    list_filter = ('created', 'modified')

Aquí el reto

Para el registro de posts solo agregé los siguiente al admin py.

from django.contrib import admin
from posts.models import Post

# Register your models here.

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    pass

Agrege un metodo para poder ir al perfil del usuario desde los post

from django.contrib import admin
from django.urls import reverse
from django.utils.safestring import mark_safe

# Models
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """Post Admin"""

    list_display = ('pk', 'profile_link', 'title', 'photo', 'created', 'updated')
    list_display_links = ('pk', 'profile_link')
    list_editable = ('title',)
    readonly_fields = ('created', 'updated',)

    fieldsets = (
        ('User', {
            'fields': (('user', 'profile'),)
        }),
        ('Post', {
            'fields': (('title',), ('photo',))
        }),
        ('Meta Data', {
            'fields': (('created', 'updated'),)
        })
    )

    def profile_link(self, obj):
        return mark_safe('<a href="{}">{}</a>'.format(
            reverse("admin:users_profile_change", args=(obj.profile.pk,)),
            obj.user.email
        ))

    profile_link.short_description = 'profile'

Hola a todos. Así me quedo mi PostAdmin

from posts.models import Post

from django.contrib import admin

# Register your models here.
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):

    list_display       = ('pk','profile','get_website','title','photo')
    list_display_links = ('pk','title')
    list_editable      = ('photo','profile')
    search_fields      = ('profile__user__username','title',)
    list_filter        = ('created_at','modified','profile__user__is_active')

    fieldsets = (
        ('Post',{
            'fields':(
                ('profile','title','photo')
            )
        }),
        ('Metadata',{
            'fields':(
                ('created_at','modified')
            )
        }),
    )
    readonly_fields = ('created_at', 'modified')

    @admin.display(ordering='profile__website', description='User website')
    def get_website(self, obj):
        return obj.profile.website

Aquí mi solución, modelo:

class Post(models.Model):

    id = models.BigAutoField(primary_key=True)

    autor = models.ForeignKey(User, on_delete=models.CASCADE,)
    
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True )
    
    title = models.CharField(max_length=200)

    image = models.ImageField(
        upload_to='posts/photos',
        blank=True,
        null=True
        )
    

    created = models.DateTimeField(auto_now_add=True)

    modified = models.DateTimeField(auto_now=True)

    
    def __str__(self):
        return f'{self.title} by {self.autor}'

admin:

@admin.register(Post)
class PostProfile(admin.ModelAdmin):

    list_display = ['id','autor', 'title', 'image']

    list_display_links = ['id','autor']

    list_editable = ['title', 'image']

    search_fields = ['autor', 'title']

    list_filter = ['created', 'modified','title']

    fieldsets = (
        ('Personal Info', 
        {'fields':(
        ('autor', 'image'), 'title'),
        }
        ),
        
        ('Metadata', {'fields':(
            ('created', 'modified')
        )
        }),
    )

    readonly_fields = ['created', 'modified']

Así me quedo el registro en admin:

from django.contrib import admin
from posts.models import Post
# Register your models here.

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """Posts Admin model"""

    list_display = ('pk', 'user', 'title', 'photo')
    list_display_links = ('pk', 'user')
    list_editable = ('photo', 'title')
    list_filter = (
        'created',
        'modified'
    )
    search_fields = ('user__username', 'title')
    readonly_fields = ('created', 'modified')

Reto resuelto:

from django.contrib import admin
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):

    list_display = ("pk", "user", "title", "photo",)
    list_display_links = ("pk", "user")
    list_editable = ("title", "photo")

    search_fields = (
        "user__username",
        "user__email",
        "title"
    )

    list_filter = (
        "created",
        "modified",
    )

Reto:

from django.contrib import admin
from django.db import models
# Models
from posts.models import Post
# Register the post models on the admin interafce.
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """Post admin"""
    list_display = ('pk','user', 'title', 'photo', 'created', 'modified')
    list_editable = ('title', 'photo')
    search_fields = ('user', 'title')
    list_filter = ('created', 'modified')

    fieldsets = (
        ('User', {'fields': (('user', 'profile'),)}),
        ('Post', {'fields': (('title', 'photo'),)}),
        ('Metadata', {'fields': (('created', 'modified'),)})
    )

    readonly_fields = ('created', 'modified')

Para acceder a assets en Django: editamos el módulo de URLs, en el que importamos static de django.conf.urls.static. al final agregamos de urlpatterns, fuera de la lista: + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT), también tenemos que importar settings, no antes de añadir dentro del archivo settings.py, MEDIA_ROOT = os.path.join(BASE_DIR, "media") y luego abajo, MEDIA_URL = "/media/" , de forma que acabamos de indicarle a Django, que busque en otro lugar, para dar devuelta, nuestros assests, en caso de que estos empiezen con media.

Django, no está por default, listo para mostrar contenido mp4, png o jpg.

Como en algunas ocaciones, se pueden generar importanciones circulares, algunas veces dentro de algunos métodos de models. podemos utilizar una ruta en un string. escribiendo, el nombre de la app, punto, el nombre de la clase: ForeignKey("users.Profile", on_delete=CASCADE)

Para nuestro modelo de Post: user = models.ForeignKey(User, on_delete=models.CASCADE), profile = models.ForeignKey(Profile, on_delete=models.CASCADE), tittle = models.CharField(max_length=260), photo = models.ImageField(upload_to="posts/photos"), created = models.DateTimeField(auto_now_add=True), modified = models.DateTimeField(auto_now=True)

I know this commonly solved by deleting de sqlite3 DB that is used in the development process.

Also, I know this question is currently solved, but I want to leave my case here as an alternative.

Sometimes while we are programming we change a lot of things in our models. When we run python manage.py makemigrations a file is created inside of our app folder/migrations. And when we run python manage.py migrate a record in the table django_migrations is created. this record contains 3 fields we must check in detail:

  • <h6>1 - name (this is the file name created in the migrations app folder)</h6>
  • <h6>2 - app (this is the name of our app. Also works like a namespace to prevent conflicts)</h6>
  • <h6>3 - applied (this is the date-time when the migration was executed).</h6>

If you’ve modified your model previously, you should have several files inside migrations (amount accordingly with the times you’ve executed makemigrations on every change), in my case I wanted to erase these files just to have only one migration file.

The problem with this is that when makemigrations was run again it creates a file 0001_initial.py. If you remember the table django_migrations contains a log of this file, this is to prevent the execution of migrations that already have been done.

If this is your case, you would erase the records of your app migrations from this table.

#user admin clases


#Django
from django.contrib import admin


#models

from posts.models import Post

# Register your models here.

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    #profile admin
    list_display = ('pk', 'user', 'profile', 'title', 'photo')
    list_display_links = ('pk','user')
    list_editable = ('title', 'photo')
    # # search_fields = ('user__username', 'user__email', 'user__first_name', 'user__last_name', 'phone__number',)
    list_filter = ('created','modified','user__is_active', 'user__is_staff',)


    fieldsets = (
        ('user', {
            'fields':(('user', 'profile'),),
        }),

        ('Extra info', {
            'fields': (
                ('title','photo'),
            ),
        }),

        ('metadate', {
            'fields': (
            ('created', 'modified'),
            
            ),
        }),
    )


    readonly_fields = ('created', 'modified')

para el reto:

from django.contrib import admin
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """post admin model"""
    list_display = ('pk','user','title','photo',)
    list_display_links= ('pk','user',)
    list_editable = ('title','photo',)

    search_fields = ('user__username', 'title','created')

    list_filter = ('created', 'modified')

Así registré el modelo en el admin, no le coloqué los list_display o alguna otra propiedad para más adelante cutomizalo a profundidad

# Django
from django.contrib import admin

# Models
from posts.models import Post
from django.contrib.auth.models import User

# Registrar un modelo de la base de datos en el admin de django
@admin.register(Post)
class ProfileAdmin(admin.ModelAdmin):
    pass```

Una consulta. El profe dice que profile no es necesario, pero ¿sería posible acceder desde user a profile? Lo digo porque user al ser un modelo de DJANGO no tiene implementada una propiedad PROFILE, como sí lo tiene Profile para USER.

¿Cómo puedo hacer que cuando le di click al usuario me redirija a este y no al post?

consulta si ya tienes el user para que profile si un profile esta atado a un user, is tienes un user no por asociación ya tenemos el profile?, no tabaja así Django?

Por qué Django no debería servir multimedia ?

Cómo hago para actualizar la versión de python en un proyecto que utilizaba una versión anterior?

😃

"""User admin classes"""

# Django
from django.contrib import admin

# Models
from posts.models import Post

@admin.register(Post)
class ProfileAdmin(admin.ModelAdmin):
    """ Post admin model."""

    list_display = ('pk', 'user', 'photo', )
    list_display_links = ('pk','user',)
    list_editable=('photo',)

Así registre el Post al admin

#Django
from django.contrib import admin
#Models

from posts.models import Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('pk','user','title','photo')
    list_display_links = ('pk','user')
    list_editable = ('title','photo')
    search_fields = ('user__username','title')
    list_filter = ('created','modify')

Mi PostAdmin

# django
from django.contrib import admin

# posts
from posts.models import Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('pk', 'user', 'title', 'created', 'modified',)
    list_display_links = ('pk', 'title',)
    list_filter = ('user__username', 'created',)
    search_fields = ('user__username', 'title',)

    fieldsets = (
        ('Post Data', {
            "fields": (
              ('user', 'profile',), ('title', 'photo'),
            ),
        }),
        ('Metadata', {
            "fields": (
              ('created', 'modified',),
            ),
        }),
    )

    readonly_fields = (
        'created', 'modified',
    )
from django.contrib import admin

from .models import Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    # Post Admin
    list_display = ('pk', 'user', 'profile', 'title',
                    'photo', 'created'
                    )
    search_fields = (
        'post__user',
        'post__profile',
        'post__title',
    )
# Django
from django.contrib import admin
# Posts
from posts.models import Post

# Register your models here.
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """Post admin"""
    list_display = ('id', 'title', 'photo', 'user')
    list_display_links = ('id', 'title')
    search_fields = (
        'title',
        'user__email',
        'user__first_name',
        'user__last_name',
        'profile__phone_number')
    list_filter = (
        'title',
        'created_at',
        'updated_at',
        'user__is_active',
        'user__is_staff')

    fieldsets = (
        ('Post Info', {
            'fields': (
                ('title', 'photo'),
            ),
        }),
        ('User Info', {
            'fields': (
                ('user', 'profile'),
            ),
        }),
        ('Metadata', {
            'fields': (
                ('created_at', 'updated_at'),
            ),
        })
    )

    def get_readonly_fields(self, request, obj=None):
        if obj:
            return ['user', 'profile', 'created_at', 'updated_at']
        else:
            return ['created_at', 'updated_at']

durante todo el curso me ha subrayado el linter un error en el self del self.user.username ?? dice “Instance of ‘ForeignKey’ has no ‘username’ member”.

alguna ayuda? Estoy usando vscode

Ya con los anteriores videos, crear un modelo parece facil, antes parecia tan complicado.

En la relación lo que se quiere decir con on_delete=models.CASCADE es que si se borra el Usuario también se borraran todos los posts. Verdad?

Hola, alguien sabe que sqlite admin maneja Pablo?

Reto

"""Posts admin classes"""

# Django
from django.contrib import admin

# Models
from posts.models import Posts

# Register your models here.


@admin.register(Posts)
class PostsAdmin(admin.ModelAdmin):
    """Posts admin."""

    list_display = ('id', 'user', 'title', 'photo', 'created_at')
    list_editable = ('title',)
    search_fields = ('user', 'user__username', 'title')
    list_filter = ('created_at', 'user__username')
"""Posts admin classes"""

# Django
from django.contrib import admin

# Models
from posts.models import Posts

# Register your models here.


@admin.register(Posts)
class PostsAdmin(admin.ModelAdmin):
    """Posts admin."""

    list_display = ('id', 'user', 'title', 'photo', 'created_at')
    list_editable = ('title',)
    search_fields = ('user', 'user__username', 'title')
    list_filter = ('created_at', 'user__username')

Dos cositas , primero creo que el modelo post le hace falta la parte del cuerpo, yo se la agregué y segundo creo que solo conectandoese con el usuario da.

dejo mi reto. salu2

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from posts.models import  Post
from django.contrib.auth.models import User

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    "Post admin model"

    list_display = ('pk', 'user', 'photo')
    list_display_links = ('pk', 'user')
    list_editable = ('photo',)
    list_filter =  ('created', 'modified')
    fieldsets = (

        ('Data', {
            'fields': (('user', 'photo'),),
        }),

        ('Post', {
                'fields' :(
                          ('title', ),
                          ('body_text',))
                          
        }),

        ('Metadata', {
            'fields': (
                ('created', 'modified'),
            )
        })
    )
    readonly_fields = ('created', 'modified')

Por qué es necesario crear una relación con user y profile, si ellos ya tienen relación?, esta relación es redundante. O estoy equivocado?

Agregar esto en posts/admin.py

from django.contrib import admin
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    verbose_name = 'Post'
    verbose_name_plural = 'Posts'

o

from django.contrib import admin
from posts.models import Post

admin.site.register(Post)

Mi post en el tablero de administración:

""" Post admin classes """

# Django
from django.contrib import admin

# Models
from posts.models import Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """ Post admin. """

    list_display = ('pk', 'title', 'photo', 'user')
    list_display_links = ('pk', 'title')
    list_editable = ('photo',)
    search_fields = ('user__username', 'title')
    list_filter = ('created', 'modified')
    fieldsets = (
        ('Author', {
            'fields': (('user', 'profile'),)
        }),
        ('Details', {
            'fields': (
                ('title', 'photo')
            )
        })
    )
    readonly_fields = ('created', 'modified')

IMPORTANTE Deben importar este modolo para que puedan utilizar el settings en urls .py

from django.conf import settings

Mi solución:

  • Remover el atributo ‘user’ de la clase Post.
  • Renombra el atributo “profile” a “author” en la clase Post.
  • Realizar los cambios pertinentes en la clase PostAdmin.

continua…

Buenos días, en mi opinión, no debe incluirse en la misma clase (Post) los atributos “user” y “profile”, dado que es redundante y permite el registro de información inconsistente en la clase Post, lo cual no representa un modelo normalizado:

Reto resuelto

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    """ Posts Admin"""
    
    list_display = ('pk', 'user', 'title','created', 'modified')

    list_display_links = ('pk', 'user', 'title')

    fieldsets = (
        ('Created By', {
            'fields': ('user',)
        }),
        ('Data', {
            'fields': (('title', 'photo'),)
        }),

    )

Django lo hace todo, crea una interfaz por modelo y los campos, vengo de rails, esto se me hace mas organizado, y bonito !! Que buena clase

Para ver las imágenes directo en el admin también ser puede hacer las utilidades que vienen en Django.

https://ilovedjango.com/django/admin/how-to-show-image-from-imagefield-in-django-admin-page/

En Django 3 ahora se usa la libreria pathlib para los directorios
Documentacion

from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib import admin

#models
from django.contrib.auth.models import User
from posts.models import Post

# Register your models here.

#forma rapida de agregar un modelo
# admin.site.register(Profile)

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):#hereda de admin.ModelAdmin
    """Profile Admin
    """


    list_display = ('pk', 'user', 'profile','title', 'photo')
    list_editable = ('title', 'photo', )```
#Reto terminado 
from django.contrib import admin
from django.contrib.auth.models import User

# Register your models here.
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display= ('pk','user','title','photo')
    list_display_links=('pk','user')
    list_editable=('title','photo')
    search_fields=('user__username','title')
    readonly_fields=('created','modified')

muy buen ejercicio

El reto de registrar post en el admin.

# Django
from django.contrib import admin

# Models
from posts.models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
	"""Posts Admin model"""

	list_display = ('pk','user', 'title', 'photo')
	list_display_links = ('pk','user')
	list_editable = ('title', 'photo')

	list_filer = (
		'created',
		'modified'
	)

	search_fields = (
		'user__username',
		'title'
	)

	readonly_fields = ('created', 'modified')

es nesesario hacer eo de las fotos