2017-09-05 3 views
1

Ich habe zwei Modelle:automatisch ausgefüllt Fremdschlüsselfeld Basierend auf Anwenderwahl Auswahl

class Entity(models.Model): 
    entity = models.CharField(primary_key=True, max_length=12) 
    entityDescription = models.CharField(max_length=200) 
    def __str__(self): 
     return self.entityDescription 

class Action(models.Model): 
    entity = models.ForeignKey(Entity, on_delete=models.CASCADE, db_column='entity') 
    entityDescription = models.CharField(max_length=200) 
    action = models.CharField(max_length=50) 
    def __str__(self): 
     return '%s' % self.entity 

Ich habe ein Modell Form und Modell formset, zusammen mit einem Formular Helfer für knusprige Formen:

class ActionForm(ModelForm): 
    class Meta: 
     model = Action 
     fields = '__all__' 
    def __init__(self, *args, **kwargs): 
     super(AlertForm, self).__init__(*args, **kwargs) 
     instance = getattr(self, 'instance', None) 
     if instance and instance.pk: 
      disabledFields = ['entity', 
           'entityDescription'] 
      for field in disabledFields: 
       self.fields[field].disabled=True 
     else: 
      self.fields['entity'].blank=True 
      self.fields['entityDescription'] = ModelChoiceField(queryset=Entity.objects.all()) 

ActionFormSet = modelformset_factory(Action, extra=1, exclude=(), form=ActionForm) 

class ActionFormsetHelper(FormHelper): 
    def __init__(self, *args, **kwargs): 
     super(ActionFormsetHelper, self).__init__(*args, **kwargs) 
     self.form_method = 'post' 
     self.template = 'bootstrap/table_inline_formset.html' 
     self.add_input(Submit("submit", "Submit")) 
     self.layout = Layout(
      Field('entity', css_class="input", type="hidden"), 
      Field('entityDescription', css_class="input"), 
      Field('action', css_class="input") 
     ) 

ich habe einen Blick:

def actions(request): 
    newActions = Action.objects.filter(action='') 
    formset = ActionFormSet(request.POST or None, queryset=newActions) 
    helper = ActionFormsetHelper() 
    context = {'formset':formset, 'helper':helper} 
    if request.method == 'POST': 
     for form in formset: 
      if form.is_valid(): 
       if form.has_changed(): 
        obj = form.save(commit=False) 
        obj.entity = form.cleaned_data['entityDescription'] 
        obj.save() 
     return HttpResponseRedirect('/actions') 
    return render(request, 'actions/actions.html', context) 

Also meine gerenderte Seite etwas wie folgt aussieht:

entityDescription action 
Jim Halpert   [Blank Cell] 
Michael Scott  [Blank Cell] 
[Blank Cell]   [Blank Cell] 

entity ist versteckt, und entityDescription wird durch das Entity Modell. Wenn der Benutzer eine entityDescription auswählt, möchte ich entity im Modell Action autopopulieren. Logisch bedeutet das entityDescription würde zurück zu dem Entity Modell gehen müssen, den entsprechenden Primärschlüssel entity finden und diesen Wert in den entity Fremdschlüssel im Action Modell setzen.

Mein Versuch ist in der Ansicht. Ich speicherte das Formular ohne zu committen, versuchte, entity einen Wert zuzuweisen, und versuchte dann, das Formular zu übergeben. Dieser Versuch führt zu diesem Fehler:

Cannot assign "<Some Entity Description>": "Action.entity" must be a "Entity" instance. 

Dies macht Sinn, weil ich versucht, nur die entityDescription zuweisen entity stattdessen die entity zuzuweisen. Ich habe versucht, neben nur die entity in einer hacky Weise zu erhalten, da es das erste Wort in entityDescription ist:

obj.entity = form.cleaned_data['entityDescription'].split(' ', 1)[0] 

Dies führte zu den gleichen Fehler, trotz entity in den Fehler zu korrigieren suchen. Diese Fehler treten sowohl für die vorhandenen Modellformsatzmitglieder als auch für das neue Mitglied auf. Wie kann ich den Primärschlüssel des Modells Entity abrufen, wenn der Benutzer einen Wert aus dem Modell Entity auswählt? Wie weise ich dann diesen Primärschlüssel dem entsprechenden Fremdschlüsselfeld im Modell Action zu?

Edit:

enter image description here

So Jim und Michael vorhandene Datensätze in Action. Der Benutzer kann ihnen eine Aktion zuweisen. Die Leerzeile ist eine neue Aktion. Der Benutzer kann das Modell entityDescription aus dem Modell Entity wählen. entity ist ein verstecktes Feld (d. H. 1 für Jim, 2 für Michael).

Wenn der Benutzer ein entityDescription für die neue Zeile auswählt (das heißt Benutzer wählt Jim), sollte der Primärschlüssel (1) in das verborgenen entity Feld eingegeben werden, bevor die Formen speichern.

Ein weiterer Edit:

Nach einer weiteren Untersuchung, wenn ich die Lösung in der Antwort zur Verfügung gestellt implementieren, ist das Problem hier:

obj.entity = Entity.objects.get(pk=pk) 

Dies kehrt tatsächlich die entityDescription des Entity Modell (dh was ist definiert durch def __str__) als den Primärschlüssel. Ich habe versucht, dies zu ändern ...

obj.entity = Entity.objects.get(pk=pk).entity 

... aber dies führt in dem Primärschlüssel als String zurückgegeben wurde und nicht als Objekt. Daher kann es nicht in der Datenbank gespeichert werden. Wie würde ich diese Zeichenfolge in ein Objekt verwandeln? Mit anderen Worten, wie verwende ich die Abfragesprache, um einen Wert von einem Feld von einem Objekt eines Django-Modells zu erhalten?

Antwort

0

Ihr obj.entity sollte als Objekt zuweisen und form.cleaned_data wird nicht wieder als Objekt.

versuchen die Ausgabe davon zu drucken, was, wenn ich Ihren Fall folgenden, makesure es als id/pk von der ausgewählten Einheit:

print(form.cleaned_data['entityDescription']) 
# eg: 16 

Dann:

obj.entity = form.cleaned_data['entityDescription'] 

sein sollte;

pk = form.cleaned_data['entityDescription'] 
obj.entity = get_object_or_404(Entity, pk=pk) 
#   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is object instance 

# OR 

pk = form.cleaned_data['entityDescription'] 
obj.entity = Entity.objects.get(pk=pk) 
#   ^^^^^^^^^^^^^^^^^^^^^^^^^ this is object instance 
+0

Also "Entity" ist eigentlich die PK des "Entity" -Modells. Wie würde ich "entity" anstatt "entityDescription" zurückgeben? Der Benutzer wählt "entityDescription", aber ich möchte, dass "entity" in "entity" im "Action" -Modell platziert wird. –

+0

'pk = form.cleaned_data ['entityDescription']. Split ('', 1) [0]' funktioniert für bestehende Mitglieder des Model-Formsets, aber wenn der Benutzer neue Informationen eingibt (dh BEIDE 'entityDescription' eingeben muss) und "action") funktioniert es immer noch nicht. Logischerweise muss ich 'entityDescription' verwenden, um das 'Entity'-Modell abzufragen und das tatsächliche PK-Objekt (' entity') zurückzugeben. –

+0

können Sie 'Entity.objects.get_or_create (pk = pk)' –

Verwandte Themen