No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Model forms

26/37
Recursos

ModelForm es una manera más sencilla de crear formularios en Django y en el caso de nuestro proyecto, se adapta mucho mejor al modelo que ya tenemos.
Lo usaremos para crear el formulario de posts.

Aprovecharemos para refinar la funcionalidad en el navbar y conectar el feed con los posts.

Aportes 35

Preguntas 17

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

posts/new.html

{% extends "base.html" %}

{% block head_content %}
<title>Create new post</title>
{% endblock %}

{% block container %}

    <div class="container">
        <div class="row justify-content-md-center">
            <div class="col-6 pt-3 pb-3" id="profile-box">
                <h4 class="mb-4">Post a new photo!</h4>

                <form method="POST" enctype="multipart/form-data">
                    {% csrf_token %}

                    <input type="hidden" name="user" value="{{ user.pk}}" />
                    <input type="hidden" name="profile" value="{{ profile.pk }}" />

                    {# Website field #}
                    <div class="form-group">
                        <input
                            class="form-control {% if form.title.errors %}is-invalid{% endif %}"
                            type="text"
                            name="title"
                            placeholder="Title"
                        >
                        <div class="invalid-feedback">
                            {% for error in form.title.errors %}{{ error }}{% endfor %}
                        </div>
                    </div>

                    {# Photo field #}
                    <div class="form-group">
                        <label>Choose your photo:</label>
                        <input
                            class="form-control {% if form.photo.errors %}is-invalid{% endif %}"
                            type="file"
                            name="photo"
                            placeholder="photo"
                        >
                        <div class="invalid-feedback">
                            {% for error in form.photo.errors %}{{ error }}{% endfor %}
                        </div>
                    </div>

                    <button type="submit" class="btn btn-primary btn-block mt-5">Publish!</button>
                </form>
            </div>
        </div>
    </div>

{% endblock %}

Para ver la sección de posts en la página del admin como el profesor:

1.- Importan la clase Post en el archivo admin.py

from posts.models import Post

2.- Crean la clase PostAdmin de la siguiente manera

class PostAdmin(admin.ModelAdmin):
    list_display = ('user', 'title', 'photo', )

3.- Registran Post y PostAdmin

admin.site.register(Post, PostAdmin)

Y con eso ya pueden ver la sección Posts como el profesor

Les recomiendo usar el paquete Django.contrib.humanize ([Django.contrib.humanize Documentation]), (https://docs.djangoproject.com/en/3.1/ref/contrib/humanize/). Con este pueden mostrar la fecha como “10 hours ago”, “three moths ago”, etc

solo deben instalarlo en los settings en INSTALLED_APPS y para usarlo en su template

{% load humanize %}
{% block content %}
   <p> This post was created {{ post.created | naturaltime }}</p>
{% end block %}

forms.Form y forms.ModelForm

¿En que casos usar uno u otro?

feed.html actualizado a sqlite

{% extends "base.html" %}

{% block head_content %}
    <title>Platzigram Feed</title>
{% endblock %}

{% block container %}
    <div class="container">
        <div class="row">
            {% for post in posts %}
            <div class="col-sm-12 col-md-8 mt-5 offset-md-2 post-container">
                <div class="media pt-3 pl-3 pb-1">
                    <img class="mr-3 rounded-circle" height="35" src="{{ post.profile.picture.url }}" alt="{{ post.user.get_full_name }}">
                    <div class="media-body">
                        <p style="margin-top:5px;">{{ post.user.get_full_name }}</p>
                    </div>
                </div>
                <img style="width: 100%" src="{{ post.photo.url }}" alt="{{ post.title }}">
                <h6 class="ml-1 mt-1">{{ post.title }}</h6>
                <p class="mt-1 ml-2">
                    <a href="" style="color: #000; font-size: 20px;">
                        <i class="far fa-heart"></i>
                    </a> 30 likes
                </p>
                <p class="ml-2 mt-0 mb-2">
                    <b>{{post.title}}</b> - <small>{{post.created}}</small>
                </p>
            </div>
            {% endfor %}
        </div>
    </div>
{% endblock %}```

Hola, nose porque cuando escribo en el src del img del profile,

{{ post.profile.picture.url }}

no me funciona como a Pablo, así que lo que hice fue colocar

{{ post.user.profile.picture.url }}

y me funcionó, pero no entiendo porque no me funciona lo otro.
alguien sabría porque o le paso lo mismo?
Me tinca que falle en algo, pero nose en que jajajaj

en windows puedes recargar en servidor con Ctrl+ D, no hay necesidad de tumbarlo y volverlo a levantar

Aproveche esta clase y hice unos cambios asi me quedo mi forms.py de Update_profile donde se hace el middleware

class UpdateForm(forms.ModelForm):

class Meta:
    model=Profile
    fields=('website','biography','picture','phone_number')

y mi vista
views.py

def update(request):
perfil=request.user.profile
print(perfil)
if request.method==‘POST’:
form=UpdateForm(request.POST,request.FILES,instance=perfil)
form.save()
else:
form=UpdateForm()

return render(
        request=request,
        template_name='users/update_profile.html',
        context={
            'form':form,
            'user' : request.user,
        }
    )

Como pueden ver la simplificacion de codigo es bastante le cambie los nombre de las clases ustedes lo tienen como update_profile

Tengo un problema, me aparece :

RelatedObjectDoesNotExist at /users/me/profile/

User has no profile.

Acá la documentación habla de qué fields debemos mostrar en el modelo para mantener el formulario seguro (y una historia de como Github fue hackeado por no seguir el consejoxd)

El FormModel valida automaticamente? Porque nunca vi validaciones ni el form que creamos ni en el model?

Podemos asignar el user y el profile al formulario desde el backend sin necesidad de exponerlos a cambios en el frontend con el inpud oculto, para esto creamos una instancia del post que vamos a guardar (pero no lo guardamos en la base de datos, añadimos los datos necesarios y luego sí guardamos en la base de datos, así:

        if form.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.profile = request.user.profile
            post.save()
            return redirect('feed')

Esto gracias al parametro commit=False en el metodo save(), que crea la instancia pero no guarda el objeto en la bdd.

Sin embargo, y es muy importante que lo tengan en cuenta un ModelForm también puede ser customizado, por lo que es más escalable, en este link la documentación explica como añadir validadores y fields propios, totalmente customizables en un ModelForm

Muy buena clase… Hay que completar el CRUD de los Posts y listo!!!
Una app genial… Django nos permite hacer aplicaciones completas de una manera muy sencilla, me ha gustado mucho!

genial!!

from django.forms import ModelForm
class PostForm(ModelForm)

Tambien es valido

La diferencia entre _forms.Form _y forms.ModelForm es que el segundo te ahorra tiempo y esfuerzo asignándole a los campos (fields) los mismos atributos que el modelo en el que se basa el formulario; mientras que por otro lado el froms.Form nos permite modificar dichos atributos.

Es por esto que en esta clase no vimos al profesor poner, por ejemplo, “required = True” a ningún campo, porque este atributo y su valor lo heredaron del modelo Post. Bastante interesante la verdad.

Excelente clase!!

Quisiera saber como crear formularios custom, por ejemplo con un dropdown no solamente que ingrese texto. Creo que seria muy util

Al momento de hacer un submit de un formulario no valido me manda a una pantalla de error en lugar de mostrar los errores del formulario en el frontend

el error dice lo siguiente:

The Post could not be created because the data didn't validate.

Request Method: 	POST
Request URL: 	http://localhost:8000/posts/new
Django Version: 	2.1.2
Exception Type: 	ValueError
Exception Value: 	

The Post could not be created because the data didn't validate.

Exception Location: 	/home/enrique/.env/lib/python3.6/site-packages/django/forms/models.py in save, line 453
Python Executable: 	/home/enrique/.env/bin/python3
Python Version: 	3.6.6
Python Path: 	

['/home/enrique/platzigram',
 '/usr/lib/python36.zip',
 '/usr/lib/python3.6',
 '/usr/lib/python3.6/lib-dynload',
 '/home/enrique/.env/lib/python3.6/site-packages']

Server time: 	Wed, 10 Oct 2018 23:31:39 +0000

😄

el pylint de visual studio saca error en esta parte posts = Post.objects.all().order_by(’-created’) , pero no afecta el funcionamiento de la aplicacion web

Excelente clase!!! todo va quedando muy chin90n!

Porque hay fotos que me salen de cabeza o volteadas 90 grados?
Alguien sabe como podria corregir eso?
Se lo agradeceria

Cuando publico un nuevo post, este se guarda en la base de datos pero cuando entro a la pagina de admin, no se agrega la linea de posts con el post que yo agregué. A alguno le ha pasado? Aun no he podido encontrar mi error y no encuentro nada diferente con el codigo del profe.

Profe. Excelente clase.

Me sale este Error:

 raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
django.core.exceptions.ImproperlyConfigured: The included URLconf 'platzigram.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.

urls.py



#django
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static

from posts import views as posts_views
from users import views as users_views

urlpatterns = [
    path('admin/', admin.site.urls, name="admin"),
    path('', posts_views.list_posts, name="feed"),
    path('posts/new', posts_views.create_post, name="create_post" ),
    path('users/login/', users_views.login_view, name="login" ),
    path('users/logout/', users_views.logout_view, name="logout" ),
    path('users/signup/', users_views.signup_view, name="signup" ),
    path('users/me/profile/', users_views.update_profile, name="update_profile")
] + static(settings.MEDIA_URL, document_root= settings.MEDIA_ROOT)

views.py posts/

"""Posts Views"""

# from django.http import HttpResponse


from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect

from posts.form import PostForm

#models
from posts.models import Post
#utilities
from datetime import datetime
# Create your views here.



@login_required
def list_posts(request):
    """List existng posts"""
    posts = Post.objects.all().order_by('-created')

    return render(request, 'posts/feed.html', {'posts': posts})


@login_required
def create_post(request):
    """create new postview"""
    profile = request.user.profile

    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)

        if form.is_valid():
            form.save()
            return redirect('feed')
    else:
        form = PostForm()

    return render(
    request= request,
    template_name= 'posts/new.html',
    context={
        'form': form,
        'user': request.user,
        'profile': profile
    })

form.py posts/

"""Post Forms"""

#django
from django import forms

#Model

from posts.models import Post

class PostForm(forms.ModelForm):
    """Post Model Form"""

    class Meta:
        """Form settings """
        model = Post
        fields = ('user','profile', 'title', 'photo')

Alguien sabe por que ?

¿Para que agrega el pk del user y profile?

El projecto es increible, y ademas te permite ir aprendiendo y adaptando el conocimiento sobre django.

new . html

{% extends "base.html" %}

{% block head_content %}
<title>Create new post</title>
{% endblock %}

{% block container %}

    <div class="container">
        <div class="row justify-content-md-center">
            <div class="col-6 pt-3 pb-3" id="profile-box">
                <h4 class="mb-4">Post a new photo!</h4>

                <form method="POST" enctype="multipart/form-data">
                    {% csrf_token %}

                    <input type="hidden" name="user" value="{{ user.pk}}" />
                    <input type="hidden" name="profile" value="{{ profile.pk }}" />

                    {# Website field #}
                    <div class="form-group">
                        <input
                            class="form-control {% if form.title.errors %}is-invalid{% endif %}"
                            type="text"
                            name="title"
                            placeholder="Title"
                        >
                        <div class="invalid-feedback">
                            {% for error in form.title.errors %}{{ error }}{% endfor %}
                        </div>
                    </div>

                    {# Photo field #}
                    <div class="form-group">
                        <label>Choose your photo:</label>
                        <input
                            class="form-control {% if form.photo.errors %}is-invalid{% endif %}"
                            type="file"
                            name="photo"
                            placeholder="photo"
                        >
                        <div class="invalid-feedback">
                            {% for error in form.photo.errors %}{{ error }}{% endfor %}
                        </div>
                    </div>

                    <button type="submit" class="btn btn-primary btn-block mt-5">Publish!</button>
                </form>
            </div>
        </div>
    </div>

{% endblock %}

Me ha salido un error nuevo que no entiendo por qué. No he tocado nada más allá de seguir las clases del profesor y me sale tanto al intentar guardar un post nuevo como al intentar entrar en el apartado de posts desde el panel de administrador.
Enlazo imagen del error (que es el mismo en ambos casos) al intentar entrar en el apartado Posts desde el administrador:

Excelente. muy bueno

si no quieres enviar el pk del user y del profile por el html, esto puede funcionar!

@login_required
def create_post(request):
    """Create new post view."""

    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.user = request.user
            form.instance.profile = request.user.profile
            form.save()
            return redirect('feed')

    else:
        form = PostForm()

    return render(
        request=request,
        template_name='posts/new.html',
        context={
            'form': form,
            'user': request.user,
            'profile': request.user.profile
        }
    )

Hola, tengo un problema. En posts/views.py no me reconoce el módulo posts. Estoy importando la clase de posts/models.py de la manera correcta (from posts.models import Post) y el editor de texto bota el error en la línea donde se declara la variable “posts” (no reconoce la clase importada ‘Post’).

from posts.forms import PostForm
from posts.models import Post


@login_required
def list_posts(request):
    """List existing posts."""
    posts = Post.objects.all().order_by('-post_date_created')

    return render(request, 'posts/feed.html', {'posts': posts})```