Giter VIP home page Giter VIP logo

django-extra-views's People

Contributors

aidanlister avatar andrewingram avatar avoine avatar cleitondelima avatar ddaan avatar dekkers avatar dmvass avatar freeworlder avatar geyser avatar jgsogo avatar jlucchese avatar jonashaag avatar lorddaedra avatar luzfcb avatar melvyn-sopacua avatar miguelrestrepo avatar mjumbewu avatar montiniz avatar pcgentry avatar pidelport avatar pmaino avatar rodrmartinez avatar sdolemelipone avatar sebcorbin avatar sergei-maertens avatar therefromhere avatar timgates42 avatar voidus avatar xrmx avatar zeus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-extra-views's Issues

Populating files

When a CreateView fails to validate and is redisplayed, inline formsets with data (text, checkbox, etc) are correctly populated. However, an inline formset for file uploads doesn't repopulate. Is there any way to do this?

Not passing request to post method.

In django-extra-views/extra_views/multi.py, line 178, you mistakenly put return self.post(_args, *_kwargs) instead of return self.post(request, _args, *_kwargs).

Prefetch related for Create/UpdateWithInlinesView

Could someone point me in the direction for how to implement prefetch_related with inline formset views? I have tried to manually override querysets, but these seem to get ignored. Am I missing something? I have a model with lots of inlines and loading the page takes very long depending on the size of the model. My other views that do much more intensive querying are almost instantaneous because of prefetch_related and select_related.

DetailWithInlineView - Where is it?

Hi Andrew,

Having spent the day reviewing your code and the tickets over on Django I can't seem to figure out how to define a:

DetailWithInlineView

I see UpdateWithInlinesView and the CreateWithInlinesView but that is for either creating the View or simultaneously updating it. Coule I ask you to show me how you would do this. FWIW I am OK with a DetailWithInlinesView (add 's').

FWIW I think you code is way more usable than rasca's enhanced-cbv. I think you should narrow this scope down to formsets and submit them into Django. This is very useful. I could help if needed.

current transaction is aborted, commands ignored until end of transaction block while using CreateWithInlinesView for GenericInlineFormSet

view

class PhoneInline(GenericInlineFormSet):
    model = Phone
    max_num = 1

class ContactCreateView(BaseSingleClient, CreateWithInlinesView):
    model = UpstreamContactModel
    inlines = [PhoneInline, ]
    template_name = 'clients/contact_form.html'

    def get_initial(self):
        initial = super(ContactCreateView, self).get_initial()
        initial = initial.copy()
        initial['client'] = self.kwargs['pk']
        return initial

models

class Phone(models.Model):
    TYPES_CHOICES = (
        ('HOME', 'Home'),
        ('WORK', 'Work'),
        ('MOBILE', 'Mobile'),
        ('HOME_FAX', 'Fax (home)'),
        ('WORK_FAX', 'Fax (work)'),
        ('PAGER', 'Pager'),
        ('OTHER', 'Other')
    )

    info = models.CharField('Phone Type', max_length=10, choices=TYPES_CHOICES)
    number = models.CharField('Phone number', max_length=20)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

class UpstreamContactModel(models.Model):
    client = models.ForeignKey(UpstreamClientModel,
            related_name='contacts')
    contact_type = models.CharField(max_length=50, default='Main', 
            blank=True, null=True)
    name = models.CharField(max_length=100, unique=True)
    job_title = models.CharField(max_length=50, blank=True, null=True)
    email = models.EmailField(blank=True, null=True)
    skype_id = models.CharField(max_length=30, blank=True, null=True)
    phones = generic.GenericRelation(Phone)
    notes = models.TextField(blank=True, null=True)

    def __unicode__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('client_list')

    class Meta:
        verbose_name = 'Contact'

traceback and debug:

(0.019) SELECT "clients_upstreamclientmodel"."id",

"clients_upstreamclientmodel"."client_name",
"clients_upstreamclientmodel"."url",
"clients_upstreamclientmodel"."language",
"clients_upstreamclientmodel"."is_active" FROM
"clients_upstreamclientmodel" WHERE "clients_upstreamclientmodel"."id"
= 1 ; args=(1,) DEBUG (0.000) SELECT (1) AS "a" FROM "clients_upstreamclientmodel" WHERE "clients_upstreamclientmodel"."id"
= 1 LIMIT 1; args=(1,) DEBUG (0.001) SELECT (1) AS "a" FROM "clients_upstreamcontactmodel" WHERE
"clients_upstreamcontactmodel"."name" = 'saasasa' LIMIT 1;
args=(u'saasasa',) DEBUG (0.001) INSERT INTO
"clients_upstreamcontactmodel" ("client_id", "contact_type", "name",
"job_title", "email", "skype_id", "notes") VALUES (1, 'Main',
'saasasa', 'sasasas', '', '', '') RETURNING
"clients_upstreamcontactmodel"."id"; args=(1, u'Main', u'saasasa',
u'sasasas', u'', u'', u'') ERROR Internal Server Error:
/clients/1/contacts/create/ Traceback (most recent call last): File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/core/handlers/base.py",
line 111, in get_response
response = callback(request, _callback_args, *_callback_kwargs) File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/views/generic/base.py",
line 48, in view
return self.dispatch(request, _args, *_kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/utils/decorators.py",
line 25, in _wrapper
return bound_func(_args, *_kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/contrib/auth/decorators.py",
line 20, in _wrapped_view
return view_func(request, _args, *_kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/utils/decorators.py",
line 21, in bound_func
return func(self, _args2, *_kwargs2) File "/Users/mirkocrocop/workspace/upstream_backend/my_auth/mixins.py",
line 22, in dispatch
return super(LoginRequiredMixin, self).dispatch(_args, *_kwargs) File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/views/generic/base.py",
line 69, in dispatch
return handler(request, _args, *_kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/extra_views/advanced.py",
line 76, in post
return super(BaseCreateWithInlinesView, self).post(request, _args, *_kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/extra_views/advanced.py",
line 62, in post
return self.forms_valid(form, inlines) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/extra_views/advanced.py",
line 25, in forms_valid
self.object = form.save() File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/forms/models.py",
line 364, in save
fail_message, commit, construct=False) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/forms/models.py",
line 86, in save_instance
instance.save() File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/db/models/base.py",
line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update) File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/db/models/base.py",
line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw) File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/db/models/manager.py",
line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/db/models/query.py",
line 1593, in insert_query
return query.get_compiler(using=using).execute_sql(return_id) File
"/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/django/db/models/sql/compiler.py",
line 910, in execute_sql
cursor.execute(sql, params) File "/Users/mirkocrocop/.virtualenvs/upstream_backend/lib/python2.7/site-packages/debug_toolbar/utils/tracking/db.py",
line 152, in execute
'iso_level': conn.isolation_level, InternalError: current transaction is aborted, commands ignored until end of transaction
block

CreateWithInlinesView doesn't save

Hi,

Im doing a proyect with a master-detail form using CreateWithInlinesView for this functionallity,

but it doesn't save, simply the page is reloaded but with the same data in screen, and doesnt commit the transaction.

When the save button is clicked, nothings happen... any error, any message

Some help will be apreciate please!

_Models.py_

class Rekuest(AuditTable):
    TYPEOWNER_CHOICES = (
        ('Empresarial', _(u'Enterprise')),
        ('Particular', _(u'Private'))        
    )

    code                = models.CharField(max_length=50, editable=False)
    bpartner            = models.ForeignKey(BPartner, verbose_name=_(u'Client'))    
    policy_type         = models.ForeignKey(PolicyType)
    type_owner          = models.CharField(_(u'Type Owner'), max_length=15, choices = TYPEOWNER_CHOICES)
    concept             = models.CharField(_(u'Concept'), max_length=60, blank='True')
    orderdate           = models.DateField(_(u'Order Date'))
    status              = models.ForeignKey(Status)
    requestedddate      = models.DateTimeField(_(u'Requested Date'), null=True, blank=True)
    finisheddate        = models.DateTimeField(_(u'Finished Date'), null=True, blank=True)    
    promise_date        = models.DateField(_(u'Promise Date'))    
    email               = models.EmailField(_(u'Email'),null=True,blank=True)
    is_active           = models.BooleanField(_(u'Active'), default=True)


    def get_next_code(self):
        # Autocalculate next Request code
        if not self.code and self.id:
            num = 1
            try:
                lastcode = Rekuest.objects.exclude(pk=self.id).order_by('-id')[0].code
                parts = lastcode.split('-')
                num = int(parts[1]) + 1
            except:
                pass

            return '%d-%03d' % (self.date.year, num)
        else:
            return self.code


    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        self.code = self.get_next_code()
        return AuditTable.save(self, force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)

    def __unicode__(self):
        return "[" + str(self.id) + "][" + str(self.orderdate) + "] " + self.bpartner.commercial_name

    class Meta:
        verbose_name = _('Request')
        verbose_name_plural = _('Requests')


class RekuestDet(AuditTable):
    CURRENCY_CHOICES = (
        ('MXN', _(u'MXN')),
        ('USD', _(u'USD'))        
    )

    numrequest          = models.ForeignKey(Rekuest, db_column='Rekuest_id')
    bpartner_vendor     = models.ForeignKey(BPartner, verbose_name=_(u'Insurance'))
    currency            = models.CharField(_(u'Currency'), max_length=15, choices = CURRENCY_CHOICES, default='MXN')
    deductible          = models.DecimalField(_(u'Deductible'), default=0,max_digits=15,decimal_places=2)    
    contact_name        = models.CharField(_(u'Contact Name'),max_length=60)
    phone1              = models.CharField(_(u'Phone'),max_length=60,blank='True')
    paymentterm         = models.ForeignKey(PaymentTerm, null='True')
    description         = models.TextField(_(u'Description'),max_length=200,null='True',blank='True')
    num_cotization      = models.TextField(_(u'Cotization No.'),max_length=20,null='True',blank='True')
    priority            = models.SmallIntegerField(_(u'Priority'),default=0,max_length=2)
    price               = models.DecimalField(_(u'Price'),default=0,max_digits=15,decimal_places=2)
    tax                 = models.DecimalField(_(u'Price'),default=0,max_digits=15,decimal_places=2)
    charges             = models.DecimalField(_(u'Price'),default=0,max_digits=15,decimal_places=2)
    others_charges      = models.DecimalField(_(u'Price'),default=0,max_digits=15,decimal_places=2)
    total               = models.DecimalField(_(u'Price'),default=0,max_digits=15,decimal_places=2)

    def get_absolute_url(self):
        return None

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        #self.calculate()
        return AuditTable.save(self, force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)

    class Meta:
        verbose_name = _('Request Detail')
        verbose_name_plural = _('Request Detail')

_Forms.py_

class RekuestForm(forms.ModelForm):

    orderdate = forms.DateField(widget=AdminDateWidget, initial=datetime.date.today, label=_(u'Date'))    
    promise_date = forms.DateField(label=_('Promised Date'), initial=datetime.date.today, required=False)

    class Meta:
        model = Rekuest
        #exclude = ('company',)


class RekuestDetForm(forms.ModelForm):

    price = forms.DecimalField(localize=True, decimal_places=2)
    quantity = forms.IntegerField(localize=True)

    class Meta:
        model = RekuestDet


class RekuestDetInline(InlineFormSet):
    model = RekuestDet
    extra = 1  #extra = Numero de renglones del detalle que mostrara al crear un registro del Master  
    form_class = RekuestDetForm    

_Views.py_

class RekuestCreateView(NamedFormsetsMixin, CreateWithInlinesView):
    model = Rekuest
    form_class = RekuestForm
    template_name = "op/request_form.html"


    inlines = [RekuestDetInline]
    inlines_names = ['RekuestDetInline']

    def get_context_data(self, **kwargs):
        ctx = super(RekuestCreateView, self).get_context_data(**kwargs)
        ctx['title'] = _("Create new Request")
        return ctx

    def get_form(self, form_class): 
        form = CreateWithInlinesView.get_form(self, form_class)
        #Filtra los Socios de Negocio por tipo=Cliente        
        form.fields['bpartner'].queryset = BPartner.objects.filter(iscustomer='True')
        return form

    def construct_inlines(self):
        #Filtra el socio de negocio del detalle por tipo=Proveedor (Aseguradora)
        inlines = CreateWithInlinesView.construct_inlines(self)
        RekuestDetInline = inlines[0]                        
        RekuestDetInline.form.base_fields['bpartner_vendor'].queryset = BPartner.objects.filter(isvendor=True)                    
        return inlines

    def forms_invalid(self, form, inlines):
        messages.error(
            self.request,
            "Your submitted data was not valid - please correct the below errors")
        return super(RekuestCreateView, self).forms_invalid(form, inlines)

    def forms_valid(self, form, inlines):
        # Default company
        #self.object.company = self.request.user.company

        # Save object to recalculate totals
        out = CreateWithInlinesView.forms_valid(self, form, inlines)
        self.object.save()
        messages.success(self.request, "Request %s saved." % (self.object.code,))
        return out

_request_form.html_

<form action="." method="post" id="request_form" class="form-horizontal wysiwyg" enctype="multipart/form-data">
    {% csrf_token %}

    <fieldset>
        <div class="well">
            <legend>
                Nueva Solicitud
            </legend>               
        </div>

        <table border="0" cellspacing="5" cellpadding="5">
            <tr>
                <td>{% trans 'Code' %}</td><td><span id="code" class="uneditable-input">{{object.code|default:''}}</span></td>
                <td>{{form.orderdate.label}}</td><td>{{form.orderdate}}</td>
            </tr>
            <tr>
                <td>{{form.bpartner.label}}</td><td>{{form.bpartner}}</td>
                <td>{{form.type_owner.label}}</td><td>{{form.type_owner}}</td>
                <td>{{form.policy_type.label}}</td><td>{{form.policy_type}}</td>
            </tr>
            <tr>
                <td>{{form.concept.label}}</td><td>{{form.concept}}</td>
                <td>{{form.promise_date.label}}</td><td>{{form.promise_date}}</td>
                <td>{{form.status.label}}</td><td>{{form.status}}</td>
            </tr>            
        </table>
        <br/>

        <fieldset class="module aligned ">
        <table class="table">
             <tr>
                <th>{% trans 'Insurance' %}</th>
                <th>{% trans 'Agent' %}</th>
                <th>{% trans 'Currency' %}</th>
                <th>{% trans 'Payment Term' %}</th>
                <th>{% trans 'Deductible' %}</th>
                <th>{% trans 'Delete' %}</th>                
             </tr>
             {{ RekuestDetInline.management_form }}
             {% for f in RekuestDetInline %}
                  <tr class="RekuestDetInline" id="id_{{ RekuestDetInline.prefix }}-{{forloop.counter0}}">
                      <td>{{f.id}}                            
                          {{f.bpartner_vendor.errors.as_ul}}{{f.bpartner_vendor}}</td>
                      <td>{{f.contact_name.errors.as_ul}}{{f.contact_name|add_class:"input-small"}}</td>
                      <td>{{f.currency.errors.as_ul}}{{f.currency|add_class:"input-small"}}</td>
                      <td>{{f.paymentterm.errors.as_ul}}{{f.paymentterm}}</td>

                      <td class="numberfield field-base"><span>{{f.deductible}}</span></td>
                      <td>{{f.DELETE}}</td>
                  </tr>
             {% endfor %}
        </table>
        </fieldset>

    </fieldset>
    <button class="btn btn-primary btn-large" type="submit">{% trans "Save" %}</button>

</form>

Form for inline on CreateWithInlinesView?

#views
class FooCreate(CreateWithInlinesView):
    model = Foo
    form_class = FooForm
    inlines = [BarInline]

class BarInline(InlineFormSet):
    model = Bar

#forms
# No BarForm!

CreateWithInlinesView seems to be ignoring the form I created. The above code works with no error, the view will automatically generate the form based on model fields. However, if I create BarForm and add form_class = BarForm to BarInline, I get a TypeError: metaclass conflict.

How do I use my own form for an inline?

SortableListMixin(ContextMixin) breaks pagination for ListView

Tested in Django 1.4.5

class SortableListMixin(object):
    # both sorting and pagination works.
    ....

class SortableListMixin(ContextMixin):
    # breaks pagination, but sorting works.
    ....

class MyListView(SortableListMixin, ListView): 
    # Sorting works, pagination doesn't
    paginate_by = 10

class MyListView(ListView, SortableListMixin):
    # Pagination works, sorting doesn't
    paginate_by = 10

Better package description

I just added django-extra-views to DjangoPackages.com

http://djangopackages.com/packages/p/django-extra-views/

I would suggest adding a better description to your github repo that explains the real purpose of this app so others can find it more easily.

Honestly I think it needs a name like "django-formset-views" or something like that, but maybe thats a pain to move around on github.

Thanks!

Define sane defaults for required attributes

For example the UpdateWithInlines needs inlines defined and for it to be iterable. It's much easier to spot this if there is a placeholder which is []. Alternatively we could define it as None and raise a helpful error, similarly to how django does if you don't define a Model or queryset.

In this particular case this may be helped by a get_inlines method, which throws NotYetImplemented if the attribute is not defined properly.

Python 3 Syntax error on install

When installing using django 1.6.2 and python 3.3.5:

$ pip install django-extra-views
Downloading/unpacking django-extra-views
  Downloading django-extra-views-0.6.4.tar.gz
  Running setup.py (path:/py33_django16/build/django-extra-views/setup.py) egg_info for package django-extra-views

Requirement already satisfied (use --upgrade to upgrade): Django>=1.3 in /py33_django16/lib/python3.3/site-packages (from django-extra-views)
Installing collected packages: django-extra-views
  Running setup.py install for django-extra-views

      File "/py33_django16/lib/python3.3/site-packages/extra_views/multi.py", line 35
        except ValidationError, e:
                              ^
    SyntaxError: invalid syntax

Successfully installed django-extra-views
Cleaning up...

ManagementForm Missing on CreateWithInlinesView

How/Where is the management form in the context? I tried both {{ inlines.management_form }} and {{ form.management_form }}, but these don't work - hence the form doesn't validate.

Using the simplest case, almost directly from the documentation:

class SQDetailsInline(InlineFormSet):
    model = SQDetails
    fields = ('terminal','merchant',)
    exclude = ('pk','id','account')
    can_delete = False
    fk_name = 'account'

class CreateOrderView(CreateWithInlinesView):
    model = SQAccount
    inlines = [SQDetailsInline]
    template_name = 'enter-order.html'

    def formset_valid(self,form):
        print form # this is here to force a 500

extra_views/multi.py need a documentation

Hello @AndrewIngram, no documentation was created for "multi" module because it is not usable or lack of available time to create it?
A minimal documentation for this module would be great.
I'm a little lost on the correct way to use it

nice project, thanks.

Problem with form_valid method at class CreateWithInlinesView

Hi!

I'm trying to implement a form with inline fields, where I have a field at my form that will be filled after the post, but it is excluded from the form. I do this at form_valid method, as described at my code bellow. I've perceived that form_valid is not woking but CreateWithInlinesView is a derivative from FormView where the method form_valid is native. Can you bring some help with this issue? Thanks so much!

class CampaignCreateView(CreateWithInlinesView):

     model = Campaign
     inlines = [CampaignListsInline, ScheduleProgramInline, ManualScheduledSendInline]
     template_name = "campaigns/campaign/campaign_add.html"
     success_url = '/campaigns/campaign/'
     form_class = CampaignForm

     def form_valid(self, form):
        """ Associate the record to the customer """
        form.instance.customer = self.request.user.get_profile().customer
        return super(CampaignCreateView, self).form_valid(form)

     @method_decorator(login_required)
     def dispatch(self, *args, **kwargs):
        return super(CampaignCreateView, self).dispatch(*args, **kwargs)

ModelFormSetMixin/BaseInlineFormSetMixin assumes the model attribute is set

They both use self.model which does not need to be set at all for the other cases.

I suggest adding a get_model method to the BaseFormSetMixin which tried to get the model from self.model and otherwise get's it from the self.get_queryset().model

Thus removing the need to define a queryset and a model.

Y U NO PUSH TAGS????

Can you push your tags from releases to Github, so it's easier to see what changed between releases?

git push --tags

Is ModelFormSetView.extra ignored?

I'm trying to integrate extra_views in a project but I stumbled across what appears to be a bug: if I set an "extra" attribute for my class, it seems to have no effect. Curiously, I get 5 extra objects - not even the 2 extra objects that appear to be the default for BaseFormSetMixin.
Am I doing something wrong?

pagination for modelsetview

Just a crude starting point - the big issue here is that construct_form is called before get_context_data which is where django's multipleobjectmixin does the pagination work and modifies the queryset.

from extra_views.formsets import BaseModelFormSetView
from extra_views.compat import ContextMixin
from django.views.generic.list import MultipleObjectTemplateResponseMixin

class ModelFormSetView(MultipleObjectTemplateResponseMixin, BaseModelFormSetView):
"""
A view for displaying a model formset, and rendering a template response
"""

def get(self, request, *args, **kwargs):
    self.object_list = self.get_queryset()
    context = self.get_context_data()

    return self.render_to_response(context)

def get_context_data(self, **kwargs):
    """
    Get the context for this view.
    """
    queryset = kwargs.pop('object_list', self.object_list)
    page_size = self.get_paginate_by(queryset)
    context_object_name = self.get_context_object_name(queryset)

    if page_size:
        paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
        formset = self.construct_formset()
        context = {
            'paginator': paginator,
            'page_obj': page,
            'is_paginated': is_paginated,
            'object_list': queryset,
        }
    else:

        context = {
            'paginator': None,
            'page_obj': None,
            'is_paginated': False,
            'object_list': queryset,
            'formset': formset
        }

    if context_object_name is not None:
        context[context_object_name] = queryset

    self.queryset = queryset
    context['formset'] = self.construct_formset()

    return ContextMixin.get_context_data(self, **context)

MultiFormView Forms that aren't validated as part of a group in POST should be instantiated as if a GET

Currently all forms are instantiated based on the POST data, whether or not they end get getting validated. This means that when the page is finally rendered they have empty data rather than their initial data, for example a formset will have no form rows rather than showing the real initial data.

So the way forms need to be instantiated AFTER we know what group was POSTed, so we can prevent forms outside of the group being given the data and files. At the moment we use the same approach for instantiation that we do with GET, this may need to change.

py3k support

Main issue I can see is that the hooks in Django related to py3k were introduced in 1.4.2, so I'd need to bump the required version of Django up to that,

Documentation, with recipes

At the moment this library has no real documentation, and much like Django's own class-based views, it's not obvious how to use it unless you read the source code quite carefully.

Quickest solution is to come up with a list of common use cases for the views and explain how to implement them.

Python 3 syntax error

When trying to pip install in environment using python 3.3.3, django 1.6.2:

$ pip install django-extra-views
Downloading/unpacking django-extra-views
  Downloading django-extra-views-0.6.4.tar.gz
  Running setup.py (path:/.virtualenvs/py33_django16/build/django-extra-views/setup.py) egg_info for package django-extra-views

Requirement already satisfied (use --upgrade to upgrade): Django>=1.3 in /.virtualenvs/py33_django16/lib/python3.3/site-packages (from django-extra-views)
Installing collected packages: django-extra-views
  Running setup.py install for django-extra-views

      File "/.virtualenvs/py33_django16/lib/python3.3/site-packages/extra_views/multi.py", line 35
        except ValidationError, e:
                              ^
    SyntaxError: invalid syntax

Successfully installed django-extra-views
Cleaning up...

This change is rather trivial:

except ValidationError as e:

Need way to specify base class to override BaseInlineFormSet

I was referencing this StackOverflow answer about model inline formsets.

I am trying to get my inline formset to show just the queryset I specify.

As far as I can tell, line 114 of formsets.py doesn't do what it implies it will.

class BaseInlineFormSetMixin(BaseFormSetMixin):
    # ...
    formset = BaseInlineFormSet
    # ...

I can't find anywhere in the code where it actually uses that specified value.

I'd like to be able to use code similar to the following and have my formset class be used when using the factory:

class BaseResponseInlineFormSet(InlineFormSet):
    model = Response
    can_delete = False
    extra = 0
    formset = GenericResponseFormSet

I'm kind of confused by the purpose of the code there. Here are my possible explanations of how a solution might look (depending on the intention of the code in the first place):

  • Change formset to formset_class
  • Declare BaseInlineFormSetMixin.get_formset_class() so it gets passed on to the factory kwargs

My workaround for now is to pass it manually into get_factory_kwargs()

Thanks!

Custom validation in `extra_views.CreateWithInlinesView`

Great job, @AndrewIngram, django-extra-views is a very useful piece of software. Maybe you could help me on this problem of mine in combination with django-extra-views:

In a extra_views.CreateWithInlinesView() I'm trying to have a custom formset validation for my inlines by overriding the clean() method of my formset.

Apparently there should be a method non_form_errors() on the formset but calling inlines.0.non_form_errors in my template won't print the errors.

Maybe some dummy code might be helpful to understand this. I stripped the non-important stuff:

class MyModelInlineFormSet(django.forms.models.BaseInlineFormSet):
   def clean(self):
       raise django.forms.ValidationError('Foobar')

class MyModelInline(extra_views.InlineFormSet):
    model = MyModel
    extra = 5
    formset_class = MyModelInlineFormSet

class MyCreateView(extra_views.CreateWithInlinesView):
    model = MyParentModel
    form_class = MyParentModelModelForm
    inlines = [MyModelInline]

And here's the part about the non_form_errors() method in the docs: https://docs.djangoproject.com/en/dev/topics/forms/formsets/#custom-formset-validation

UpdateWithInlines breaks when deleting items on multiple tabs

  1. Open 2 tabs with the same formset using UpdateWithInlines
  2. Remove one of the inlines on the first tab and click "Save".
  3. Remove the same inline on the second tab and click "Save".

RESULT
Internal Server Error. It could be

  • IndexError 'list index out of range' (when you remove the last item)
  • uncaught ValidationError: 'Select a valid choice. That choice is not one of the available choices' (when you remove other than the last item)

EXPECTED
I'm not sure what we should expect here, but definitely not uncaught generic exceptions.

OK - It ALMOST works..

Hey Andrew,

Thanks for the note - So it's working I can see the data going into the db. But the populated data is not showing back in the view.

  • Start with an empty slate.
  • Confirm no documents are listed.
  • Add a document
  • Confirmed document is showing up in the db.

But the view doesn't show anything. It's always empty. Do you have any pointers.

FWIW - It'a very basic example..

class CompanyDetailView(InlineFormSetView):
    """Details of the Company Page"""
    model = Company
    inline_model = CompanyDocument
    fk_name = "company"
    fields=('document', 'description')
    can_delete=True
    extra = 1

I suspect this has to do with the fk_name.

Use of ImageFields in inlineformsets

Hi there,

Thanks for an excellent set of views - they're very handy.

However - i don't seem to be able to get new image files to get uploaded when the forms are saved with the UpdateWithInlinesView. I suspect the contents of request.FILES isn't being bound to the model? My form definitely has an enctype="multipart/form-data" attribute.

Do you have any suggestions?

Many thanks,

Stephen

SuccessMessageMixin is useless with InlineViews

Using forms_valid() and never calling form_valid() means that the SuccessMessageMixin can't set any success messages. (form_valid() is where SuccessMessageMixin injects the messages)

To get round this, I made a new InlineSuccessMessageMixin

from django.contrib import messages


class InlineSuccessMessageMixin(object):
    """
    Adds a success message on successful form submission.
    """
    success_message = ''

    def forms_valid(self, form, formset):
        print "something"
        response = super(InlineSuccessMessageMixin, self).forms_valid(form, formset)
        success_message = self.get_success_message(form.cleaned_data)
        if success_message:
            messages.success(self.request, success_message)
        return response

    def get_success_message(self, cleaned_data):
        return self.success_message % cleaned_data

It's basically just a copy of the django's built in one.

If you were to implement this, things to note:

It doesn't pass the formset forms' cleaned_data to the success message

MultiFormView - A design pattern for handling multiple forms/formsets.

Django's generic views fall short when you want to handle multiple forms within a single view, I want to come up with a new class-based view which makes it easy to handle this along with any handling logic that may be required.

An example use case would be the Basket view on an e-commerce site. the "Add to cart" buttons around the site should post to this view, the view should render formsets of items on GET as well as handling POST. Also needs to handle save-for-later and adding voucher codes to the basket. So we've ended up where we have 4 different kinds of date modification being performed on the same resource (the basket), using separate views for this would break the post-validate-redirect loop.

I propose an API like this:

class BasketView(MultiFormView):
    forms = {
        'items': MultiFormView.modelformset(model=BasketItem),
        'add': MultiFormView.form(form=AddToBasketForm),
        'saved': MultiFormView.modelformset(model=BasketItem),
    }

    def get_items_queryset(self):
        return self.request.basket.lines.all()

    def get_saved_queryset(self):
        return self.request.saved_basket.lines.all()

    def valid_items(self, form, valid_forms):
        # Called when items is valid

    def valid_add(self, form, valid_forms):
        # etc

The form-specific methods would be called automatically using has/getattr.

Sometimes you might want two forms to be processed in the same request, so you need a way to say that they depend on each being present:

class OrderView(MultiFormView):
    forms = {
        'order': (MultiFormView.modelform(model=Order), dict(requires=('items')),
        'items': (MultiFormView.modelformset(model=OrderItem), dict(requires=('order')),
    }

    def forms_valid(self, valid_forms):
        # this only gets called if both 'order' and 'items' were present and both validated, happens after the post-validation handler for the individual forms.
        pass

Dynamically Adding forms to a Formset

Hello, this may be out of the scope of what this application is meant to do and it's more of a feature request than an issue. First off, this package is great and it makes creating formsets a breeze, but I've hit a brick wall with dynamically adding forms to a formset. I'm not particularly good with Javascript and I'm wondering if anyone has found a decent solution to this?

Assume, for examples sake, we have a form for an album which can contain a bunch of images. Initially, we would render the album form and 5 image forms. If a user wants to add more than 5 images, they could hit a button that says 'add another' which would then render another image form.

I've found a few things around the place that hint towards how to do this, but as I said, my Javascript isn't very good and I'm terrible with regular expressions so I'm having a lot of trouble matching the form IDs and incrementing them as necessary. Thanks for any help on this :) I'll keep working with what I've got and if I make any breakthroughs I'll post them up in here.

Nested Formsets

Is it possible to do nested formsets with django-extra-views? I'm thinking of something along these lines: http://yergler.net/blog/2009/09/27/nested-formsets-with-django/ ... If it is possible, how would I do it?

A secondary question: Is it possible to have a formset with nested forms? So I have a formset of Survey objects and I want each to also render/save/update a related model of

save m2m on modelformsets

modelformsets should provide a way to call save_m2m() when applicable, could be done using a boolean flag or maybe inspecting the fields to see if they include a manytomany relationship.

passing initial data to a formset, doesn't show data_changed as true / does not save data

Not sure if this is a deeper problem with Django ModelForms, or just this package.

If I have a ModelFormSetView, to add Persons objects to a Trip object. I want to add some initial data to the forms, default names for each person, "Person 1", "Person 2" etc.

class AddPersonsFormSetView(ModelFormSetView):
    model = Person
    template_name = 'AddPersons.html'
    extra = 1
    success_url = '/trip/%s/expense/add/'

     def get_formset_kwargs(self):
         kwargs = super(AddPersonsFormSetView, self).get_formset_kwargs()
         num_persons = self.kwargs['num_persons']

         ## inital data will give the name Person <increment> 
         initial = [ 
             { 'name' : "Person %s" % i , 'trip' : self.kwargs['trip_id'] }  for i in range( 1, int(num_persons)+ 1)
         ]

         kwargs.update({'initial': initial })
         return kwargs

Now if I change the values in the form, it saves correctly. If I leave the default values as they are, the PersonForm generated by the factory does not see the data_changed() as True, so doesn't save anything.

I can work around this by creating the form, overriding the has_changed method, and specifying it in the get_factory_kwargs() method of the AddPersonFormSetView but this isn't an obvious solution until you step through the code. It doesn't not feel seem correct behaviour to ignore default values.

class PersonForm(ModelForm):
    class Meta:
        model=Person   

    def has_changed(self):
        """
        Overriding this, as the initial data passed to the form does not get noticed, 
        and so does not get saved, unless it actually changes
        """
        changed_data = super(ModelForm, self).has_changed()
        return bool(self.initial or changed_data)



class AddPersonsFormSetView(ModelFormSetView):
    ... 
    ... 
    def get_factory_kwargs(self):
        kwargs = super(AddPersonsFormSetView, self).get_factory_kwargs()
        kwargs['form'] = PersonForm
        return kwargs

type object 'FooForm' has no attribute 'get_context_suffix'

I was trying to use the non-documented "extra_views/multi.py" module, and came across this error.

AttributeError at /
type object 'UserForm' has no attribute 'get_context_suffix'
Request Method: GET
Request URL:    http://127.0.0.1:8000/
Django Version: 1.6.2
Exception Type: AttributeError
Exception Value:    
type object 'UserForm' has no attribute 'get_context_suffix'
Exception Location: /home/sutransdev/1envs_virtualenv/sisposto/local/lib/python2.7/site-packages/extra_views/multi.py in construct_forms, line 92
Python Executable:  /home/sutransdev/1envs_virtualenv/sisposto/bin/python2.7
Python Version: 2.7.5
Python Path:    
['/home/sutransdev/projetos/posto/sisposto/sisposto',
 '/home/sutransdev/projetos/posto/sisposto',
 '/home/sutransdev/projetos/posto/sisposto/sisposto',
 '/home/sutransdev/1envs_virtualenv/sisposto/lib/python2.7',
 '/home/sutransdev/1envs_virtualenv/sisposto/lib/python2.7/plat-x86_64-linux-gnu',
 '/home/sutransdev/1envs_virtualenv/sisposto/lib/python2.7/lib-tk',
 '/home/sutransdev/1envs_virtualenv/sisposto/lib/python2.7/lib-old',
 '/home/sutransdev/1envs_virtualenv/sisposto/lib/python2.7/lib-dynload',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-x86_64-linux-gnu',
 '/usr/lib/python2.7/lib-tk',
 '/home/sutransdev/1envs_virtualenv/sisposto/local/lib/python2.7/site-packages']
Server time:    Qui, 3 Abr 2014 18:33:20 -0300

Multiview: change prefix container to set instead of list.

In ProcessMultiFormView:

Instead of having prefixes be a list for this section:

    posted_prefixes = []

    # First we detect which prefixes were POSTed
    for prefix in self.get_form_definitions().keys():
        for field in self.request.POST:
            if field.startswith(prefix):
                posted_prefixes.append(prefix)
                break

    # Now we iterated over the groups until we find one that matches the POSTed prefixes
    for label, prefixes in self.get_groups().iteritems():
        if label == 'all' or list(prefixes) == posted_prefixes:

Wouldn't it make more sense to have prefixes be a set? I was debugging for an hour trying to figure out why things wouldn't work, when I figured out that the computed posted_prefixes were something like ["left_form", "right_form"] and my group's prefixes (that it was comparing it to) were ["right_form", "left_form"]. Obviously these didn't match and I kept getting a 404 error. Using a set would solve this issue and simplify problems in the future.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.